Proxy(代理模式)属于结构型模式,经过访问代理对象代替访问原始对象,以得到一些设计上的便捷。前端
意图:为其余对象提供一种代理以控制这个对象的访问。git
若是看不懂上面的意图介绍,没有关系,设计模式须要在平常工做里用起来,结合例子能够加深你的理解,下面我准备了三个例子,让你体会什么场景下会用到这种设计模式。github
得到一个文本对象长度,必需要真正渲染出来,而渲染是比较耗时的,咱们可能只在某些场景下须要访问文本对象长度,而更多时候只须要读取文本内容,这两种操做耗时是彻底不一样的,如何作到业务层调用无感知,来优化执行耗时呢?typescript
代理模式能够解决这个问题,咱们将业务层使用的文本对象替换为代理对象,这个代理对象初始化并不渲染文本,而是在调用文本长度时才渲染。设计模式
某个大型系统开发完了,忽然要求增长代码访问权限体系,不一样模块对相同的底层对象拥有不一样访问权限,此时这个权限控制逻辑若是写入底层对象,就违背了开闭原则,而对象自己的实现也再也不纯粹,增长了维护成本,如何作到不修改对象自己,实现权限控制呢?前端框架
代理模式也能解决,将底层对象导出替换为代理对象,由代理对象控制访问权限便可。微信
Angular 或 Vue 这类前端框架采用双向绑定视图更新技术,即对象修改后,使用到的视图会自动刷新,这就须要作到如下两点:框架
问题是,在业务代码使用对象与修改对象的地方插入这段逻辑,显然会增长巨大的维护成本,如何作到业务层无感知呢?优化
代理模式能够很好的解决这个问题,其实业务层拿到的对象已是代理对象了,它在被访问与被修改时,都会执行固定的钩子作视图绑定与视图刷新。spa
意图:为其余对象提供一种代理以控制这个对象的访问。
代理模式的意图很容易理解,就是经过代理对象代替原始对象的访问。
这只是代理模式的实现方式,代理模式真正的难点不在于理解它是如何工做的,而是理解哪些场景适合用代理,或者说建立了代理对象,怎么用才能发挥它的价值。
在上面例子中,已经举出了几种常见代理使用场景:
使用时关系以下:
Subject 定义的是 RealSubject 与 Proxy 共用的接口,这样任何使用 RealSubject 的地方均可以使用 Proxy。
RealSubject 指的是原始对象,Proxy 是一个代理实体。
关系图中能够看出,当客户端要访问 subject 时,第一层访问的是 Proxy 代理,由这个代理将 realSubject 转发给客户端。
下面例子使用 typescript 编写。
`// 对象 obj
const proxy = new Proxy(obj, {
get(target,key) {}
set(target,key,value) {}
})
`
JS 建立代理仍是蛮简单的,代理能够控制对象的全部成员属性,包括成员变量与成员方法的访问(get)与修改(set)。
代理模式会增长微弱的开销,所以请不要将全部对象都变成代理,没有意义的代理只会徒增程序开销。
另外代理对象过多,也会致使调试困难,由于代理层的存在,咱们每每可能忽略这一层带来的影响,致使忘记这个对象实际上是一个代理。
代理和继承有足够多的类似之处,继承中,子类几乎能够人为是对父类的代理,子类能够重写父类的方法。但代理和继承仍是有区别的:
若是你没有采用 new Proxy
这种 API 建立代理,而是采用继承的方式实现,你会一会儿继承这个类的全部方法,而作不到按需控制访问权限的灵活效果,因此代理比继承更加灵活。
JS 的 new Proxy
对应了 Java 动态代理模式,通常认为动态代理比静态代理更强大。
最后,还要重申那句话,代理模式理解与运用并不难,难就难在可否在恰当的场合想到它,双向绑定几乎是代理模式最好的例子。
讨论地址是: 精读《设计模式 - Proxy 代理模式》· Issue #291 · dt-fe/weekly
若是你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。
关注 前端精读微信公众号
版权声明:自由转载-非商用-非衍生-保持署名( 创意共享 3.0 许可证)