引言
设计模式,即Design Patterns,是指在软件设计中,被反复使用的一种代码设计经验。使用设计模式的目的是为了可重用代码,提高代码的可扩展性和可维护性。
定义
结构型模式
代理模式:给某对象提供一个代理对象以控制对该对象的访问
我们设计和开发模块时,我们不希望开发人员直接访问这个模块,而是提供了另外一个 代理模块 ,通过访问代理模块间接地访问目标模块。
特点
对于代理模式而言,开发人员永远访问不到目标模块,这是 代理模式 和 装饰器模式 的区别之一。
优点
- 代理模块对目标模块起到保护作用
- 代理模块对目标模块起到增强作用
- 代理模式降低业务模块和目标模块的耦合度
如果,我们想要 保护 目标模块,防止开发人员篡改和乱用模块的属性和方法,我们考虑使用代理模式,断开和目标模块的直接关系;
如果,我们想要 扩展 功能,但是为了保证目标模块的单一职责,我们考虑使用代理模式,直接在代理模块上扩展功能;
如果,我们想要 减小 未来修改目标模块所带来的 影响,我们考虑使用代理模式,降低 模块间的 耦合度。即使将来重构目标模块,只需要对代理模块进行一些适配工作,这样就可以避免开发人员同步改动,减少不必要的bug。
缺点
- 代理模式导致模块数量增加
- 代理模式导致系统复杂增加
- 代理模式导致处理速度变慢
因为总是会多出一个代理模块,任何对目标模块的访问都需要通过代理模块来完成,从而导致 数量增加、复杂增加、速度变慢。
实现
目标模块
class TargetModule {
prop1;
props2;
method1() {
// do something
}
methods2() {
// do something
}
}
代理模块
class ProxyModule {
targetModule;
prop1;
props2;
constructor() {
this.targetModule = new TargetModule();
}
proxyMethod1() {
this.targetModule.method1();
}
proxyMethod2() {
// do others
this.targetModule.method2();
// do others
}
}
业务使用
const proxyModule = new ProxyModule();
proxyModule.proxyMethod1();
proxyModule.proxyMethod2();
应用场景
这里只讨论前端的代理场景。
- 代理服务器,实现本地跨域请求,例如:webpack-dev-server
- 代理全局环境,实现js隔离,例如:qiankun的沙箱隔离
- 代理API对象,规范和限制API的暴露
- 拦截对象的访问,执行其他逻辑,例如vue3的响应式原理、API调用时上报埋点