代理模式
为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
比如,某对象需访问目标对象,但由于某种情况,不适合或不能直接访问目标对象,通过一个中介进行访问,这个中介就是代理对象。
- 抽象主题类:可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求
- 具体主题类:被委托的类,是具体业务的执行者
- 代理类:负责对具体主题的应用,并在具体主题处理前后都增加预处理和处理后工作
在代理创建的时期,划分为静态代理和动态代理
- 静态代理:由由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
- 动态代理:在程序运行时,运用反射机制动态创建而成
// 静态代理
interface Subject {
doSave(): void;
}
class RealSubject implements Subject {
doSave() {
console.log("保存操作");
}
}
class ProxyClass implements Subject {
private realSubject?: RealSubject;
doSave() {
if (!this.realSubject) {
this.realSubject = new RealSubject();
}
this.preSave();
this.realSubject.doSave();
this.finishSave();
}
preSave() {
console.log("保存之前");
}
finishSave() {
console.log("保存之后");
}
}
// 动态代理类
class DynamicProxy {
private target: any;
constructor(target: any) {
this.target = target;
}
getInstance(): any {
return new Proxy(this.target, {
get: (target, propKey) => {
console.log('动态代理的保存之前处理...')
return target[propKey];
},
});
}
// ---- main 函数 ----
(() => {
const proxy = new ProxyClass();
proxy.doSave();
console.log('-----动态代理-----');
const instance = new DynamicProxy(new RealSubject()).getInstance();
instance.doSave();
})();
// ----输出结果----
保存之前
保存操作
保存之后
-----动态代理-----
动态代理的保存之前处理...
保存操作
其中动态代理可以看到使用了Proxy对象,这是typescript提供的Proxy对象
TypeScript中的Proxy
const proxy = new Proxy(target, handle);
- target 指所要代理的对象
- handle 也是个对象,是对 target 对象操作的拦截
再回到代码中,getInstance方法返回得到一个RealSubject类的代理,再handle里加了对目标对象的属性 get 操作的拦截,get操作中可进行一些前置操作,如输出 "console.log('动态代理的保存之前处理...')"。
Proxy中还提供其他可拦截的操作
get(target, propKey, receiver)
set(target, propKey, value, receiver)
apply(target, object, args)
defineProperty(target, propKey, propDesc)
deleteProperty(target, propKey)
has(target, propKey)
ownKeys(target)
construct(target, args)
getPrototypeOf(target)
setPrototypeOf(target, proto)
getOwnPropertyDescriptor(target, propKey)
isExtensible(target)
preventExtensions(target)
使用代理的目的是什么?
- 保护目标对象
- 增强目标对象(代理类增加对具体类的操作,如上的保存前后的操作)
代理使用场景:
- 为了隐藏目标对象时使用远程代理,如
- 当要创建的目标对象开销很大时,可以创建一个虚拟代理,如下载文件太大,创建个虚拟文件,让用户无感知服务器慢的感觉
- 安全代理,这种方式通常用于控制不同种类客户对真实对象的访问权限。
- 延迟加载,为了提高系统性能延迟对目标的加载
参考资料:
-
\