什么是代理模式

58 阅读4分钟

什么是代理模式

代理模式(Proxy Pattern)

代理模式是一种结构型设计模式,它允许你提供一个代理对象来控制对另一个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在不改变目标对象的情况下,增加额外的功能或控制访问。

代理模式的核心思想

  1. 控制访问

    • 代理对象可以控制客户端对目标对象的访问,例如延迟初始化、权限验证等。
  2. 增强功能

    • 代理对象可以在调用目标对象的方法前后添加额外的逻辑,例如日志记录、缓存、性能监控等。
  3. 解耦

    • 代理模式将客户端与目标对象解耦,客户端无需直接操作目标对象。

代理模式的组成部分

  1. Subject(抽象主题)

    • 定义目标对象和代理对象的共同接口,客户端通过该接口与目标对象交互。
  2. RealSubject(真实主题)

    • 实际的目标对象,代理对象最终会调用它的方法。
  3. Proxy(代理)

    • 代理对象,持有对真实主题的引用,并控制对它的访问。

代理模式的实现方式

  1. 保护代理

保护代理用于控制对目标对象的访问权限。

class RealSubject {
  request() {
    console.log("RealSubject: Handling request.");
  }
}

class Proxy {
  constructor(realSubject) {
    this.realSubject = realSubject;
  }

  request() {
    if (this.checkAccess()) {
      this.realSubject.request();
    } else {
      console.log("Proxy: Access denied.");
    }
  }

  checkAccess() {
    // 模拟权限检查
    console.log("Proxy: Checking access.");
    return true;
  }
}

// 使用
const realSubject = new RealSubject();
const proxy = new Proxy(realSubject);
proxy.request();

输出

Proxy: Checking access.
RealSubject: Handling request.
  1. 虚拟代理

虚拟代理用于延迟目标对象的初始化,直到真正需要时才创建。

class RealSubject {
  request() {
    console.log("RealSubject: Handling request.");
  }
}

class Proxy {
  constructor() {
    this.realSubject = null;
  }

  request() {
    if (!this.realSubject) {
      this.realSubject = new RealSubject();
    }
    this.realSubject.request();
  }
}

// 使用
const proxy = new Proxy();
proxy.request(); // 只有在调用时才会创建 RealSubject

输出

RealSubject: Handling request.
  1. 缓存代理

缓存代理用于缓存目标对象的结果,避免重复计算。

class RealSubject {
  heavyCompute(value) {
    console.log("RealSubject: Computing...");
    return value * 2;
  }
}

class Proxy {
  constructor(realSubject) {
    this.realSubject = realSubject;
    this.cache = new Map();
  }

  heavyCompute(value) {
    if (this.cache.has(value)) {
      console.log("Proxy: Returning cached result.");
      return this.cache.get(value);
    }
    const result = this.realSubject.heavyCompute(value);
    this.cache.set(value, result);
    return result;
  }
}

// 使用
const realSubject = new RealSubject();
const proxy = new Proxy(realSubject);

console.log(proxy.heavyCompute(10)); // 第一次计算
console.log(proxy.heavyCompute(10)); // 返回缓存结果

输出

RealSubject: Computing...
20
Proxy: Returning cached result.
20
  1. 远程代理

远程代理用于隐藏目标对象在网络中的位置,客户端通过代理对象访问远程服务。

// 模拟远程服务
class RemoteService {
  request() {
    console.log("RemoteService: Handling request.");
  }
}

// 远程代理
class Proxy {
  request() {
    console.log("Proxy: Forwarding request to remote service.");
    const remoteService = new RemoteService();
    remoteService.request();
  }
}

// 使用
const proxy = new Proxy();
proxy.request();

输出

Proxy: Forwarding request to remote service.
RemoteService: Handling request.

代理模式的优点

  1. 控制访问

    • 代理对象可以控制对目标对象的访问,例如权限验证、延迟初始化等。
  2. 增强功能

    • 代理对象可以在不修改目标对象的情况下,增加额外的功能,例如日志记录、缓存等。
  3. 解耦

    • 代理模式将客户端与目标对象解耦,客户端无需直接操作目标对象。
  4. 灵活性

    • 代理模式可以根据需要动态地创建和替换代理对象。

代理模式的缺点

  1. 复杂性增加

    • 引入代理对象会增加系统的复杂性,尤其是在多层代理的情况下。
  2. 性能开销

    • 代理对象可能会引入额外的性能开销,例如延迟初始化、远程调用等。
  3. 代码冗余

    • 代理对象需要实现与目标对象相同的接口,可能导致代码冗余。

代理模式的应用场景

  1. 延迟初始化

    • 当目标对象的创建成本较高时,可以使用虚拟代理延迟初始化。
  2. 访问控制

    • 当需要对目标对象的访问进行权限控制时,可以使用保护代理。
  3. 缓存

    • 当需要对目标对象的结果进行缓存时,可以使用缓存代理。
  4. 远程调用

    • 当目标对象位于远程服务器时,可以使用远程代理隐藏网络细节。
  5. 日志记录

    • 当需要在调用目标对象的方法前后记录日志时,可以使用代理模式。

总结

代理模式是一种强大的设计模式,适用于需要控制访问、增强功能或解耦的场景。通过代理对象,可以在不修改目标对象的情况下,灵活地扩展其功能。然而,代理模式也可能增加系统的复杂性和性能开销,因此在实际开发中应谨慎使用。

更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github