代理模式
大约 4 分钟约 1232 字
定义
代理模式 (Proxy Pattern)又称委托模式,它为目标对象创造了一个代理对象,以控制对目标对象的访问。
代理模式的关键是,当客户不⽅便直接访问⼀个对象或者不满⾜需要时,提供⼀个替身对象来控制这个对象的访问,客户实际上访问的是替身对象 。

这种结构可以实现在调用目标对象前和调用后进行一些预操作和后操作,从而实现新的功能或者扩展目标的功能。
使用场景
- 缓存代理:使用缓存代理可以缓存计算结果,避免重复的计算或请求。例如,可以使用缓存代理来缓存网络请求的结果,如果下次请求相同的资源,则直接返回缓存的结果而不用再次发送请求。
- 拦截器:使用代理对象作为拦截器可以拦截和处理请求、响应或事件。这在实际开发中经常用于添加额外的逻辑、验证、日志记录等操作。例如,可以使用拦截器拦截网络请求,在发送请求前添加统一的请求头或记录日志。
- 虚拟代理:使用虚拟代理可以延迟加载资源或延迟执行昂贵的操作,从而提高页面的响应速度和用户体验。例如,在图片加载时可以使用虚拟代理,只有当图片需要显示时才实际加载图片数据。
- 保护代理:保护代理可以用来限制对敏感操作或数据的访问权限。在前端开发中,可以使用保护代理来控制用户对特定功能的访问权限,例如需要登录才能进行操作的功能或需要特定权限才能查看的数据。
- 正向代理: 一般的访问流程是客户端直接向目标服务器发送请求并获取内容,使用正向代理后,客户端改为向代理服务器发送请求,并指定目标服务器(原始服务器),然后由代理服务器和原始服务器通信,转交请求并获得的内容,再返回给客户端。正向代理隐藏了真实的客户端,为客户端收发请求,使真实客户端对服务器不可见;
- 反向代理: 与一般访问流程相比,使用反向代理后,直接收到请求的服务器是代理服务器,然后将请求转发给内部网络上真正进行处理的服务器,得到的结果返回给客户端。反向代理隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。
优缺点
优点
- 控制访问:代理对象可以控制访问目标对象,从而可以在访问目标对象之前或之后执行一些额外的逻辑,例如权限校验、缓存数据等。
- 隐藏复杂性:代理模式可以封装目标对象的复杂性,使客户端对目标对象的具体实现细节进行解耦,增强了代码的可维护性和可读性。
- 增强安全性:通过代理对象可以对访问请求进行安全过滤和验证,确保数据的安全性和完整性。
- 性能优化:代理模式可以实现一些性能优化策略,例如延迟加载、数据缓存等,从而提升系统的性能和响应速度。
缺点
- 增加复杂性:引入代理对象会增加代码的复杂性,需要额外的开发和维护工作,可能会导致系统变得难以理解和维护。
- 性能损失:在使用代理模式时,会增加一定的开销,例如代理对象的创建、额外逻辑的执行等,可能会对系统的性能产生一定影响。
- 可能引入新问题:设计和实现代理模式时需要考虑到代理对象与目标对象之间的交互逻辑,如果设计不合理或实现有误,可能会引入新的问题和 bug。
实现
// 目标对象:计算器函数
class Calculator {
multiply(a, b) {
console.log(`Calculating ${a} * ${b}`);
return a * b;
}
}
// 代理对象:缓存代理
class CachingProxy {
constructor() {
this.calculator = new Calculator();
this.cache = {};
}
multiply(a, b) {
const key = `${a}*${b}`;
if (this.cache[key] === undefined) {
this.cache[key] = this.calculator.multiply(a, b);
}
return this.cache[key];
}
}
// 使用缓存代理进行乘法计算
const proxy = new CachingProxy();
console.log(proxy.multiply(2, 3)); // 第一次计算
console.log(proxy.multiply(2, 3)); // 从缓存中获取结果
console.log(proxy.multiply(4, 5)); // 新的乘法计算
console.log(proxy.multiply(4, 5)); // 从缓存中获取结果