1. 什么是代理模式?
代理模式(Proxy Pattern)是一种结构型设计模式,它允许使用代理对象来控制对目标对象的访问。代理对象通常用于以下场景:
- 控制访问:如权限控制、延迟初始化、远程访问等。
- 增强功能:如日志记录、缓存、请求限制等。
- 安全性:如隐藏真实对象的细节。
2. 代理模式的类型
2.1 静态代理
在静态代理中,代理类在编译期就已经定义好,通常是手动编写的。
interface Subject {
request(): void;
}
class RealSubject implements Subject {
request(): void {
console.log("RealSubject: 处理请求");
}
}
class ProxySubject implements Subject {
private realSubject: RealSubject;
constructor() {
this.realSubject = new RealSubject();
}
request(): void {
console.log("Proxy: 进行额外的操作(如日志记录、权限控制等)");
this.realSubject.request();
}
}
const proxy = new ProxySubject();
proxy.request();
2.2 动态代理
动态代理通常使用 Proxy 对象,它能在运行时动态地拦截对目标对象的操作。
const target = {
message: "Hello, World!",
greet(name: string) {
return `Hello, ${name}`;
},
};
const handler: ProxyHandler<typeof target> = {
get(target, prop, receiver) {
console.log(`访问属性: ${String(prop)}`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
console.log(`设置属性: ${String(prop)} = ${value}`);
return Reflect.set(target, prop, value, receiver);
},
};
const proxyObj = new Proxy(target, handler);
console.log(proxyObj.message);
proxyObj.message = "Hello, Proxy!";
console.log(proxyObj.greet("Alice"));
3. 代理模式的应用场景
3.1 缓存代理
在某些情况下,我们可以使用代理模式来缓存计算结果,以提高性能。
class ExpensiveOperation {
compute(value: number): number {
console.log(`执行计算: ${value} * ${value}`);
return value * value;
}
}
class CachedProxy {
private realSubject: ExpensiveOperation;
private cache: Map<number, number>;
constructor() {
this.realSubject = new ExpensiveOperation();
this.cache = new Map();
}
compute(value: number): number {
if (this.cache.has(value)) {
console.log("从缓存中获取结果");
return this.cache.get(value)!;
}
const result = this.realSubject.compute(value);
this.cache.set(value, result);
return result;
}
}
const proxyCache = new CachedProxy();
console.log(proxyCache.compute(5));
console.log(proxyCache.compute(5));
3.2 访问控制代理
对于某些敏感操作,我们可以使用代理模式来限制访问。
class SecureData {
getSecret(): string {
return "敏感数据";
}
}
class SecurityProxy {
private realSubject: SecureData;
private userRole: string;
constructor(userRole: string) {
this.realSubject = new SecureData();
this.userRole = userRole;
}
getSecret(): string {
if (this.userRole !== "admin") {
throw new Error("权限不足,无法访问数据");
}
return this.realSubject.getSecret();
}
}
try {
const secureProxy = new SecurityProxy("guest");
console.log(secureProxy.getSecret());
} catch (error) {
console.error(error.message);
}
4. 总结
代理模式在 TypeScript 开发中有着广泛的应用,尤其是动态代理,它提供了一种灵活的方式来增强对象的功能,例如日志记录、缓存、访问控制等。在实际开发中,可以根据需求选择合适的代理模式,提高代码的可维护性和扩展性。