TypeScript设计模式(6):代理模式

182 阅读2分钟

1. 什么是代理模式?

代理模式(Proxy Pattern)是一种结构型设计模式,它允许使用代理对象来控制对目标对象的访问。代理对象通常用于以下场景:

  • 控制访问:如权限控制、延迟初始化、远程访问等。
  • 增强功能:如日志记录、缓存、请求限制等。
  • 安全性:如隐藏真实对象的细节。

2. 代理模式的类型

2.1 静态代理

在静态代理中,代理类在编译期就已经定义好,通常是手动编写的。

interface Subject {
  request(): void;
}

class RealSubject implements Subject {
  request(): void {
    console.log("RealSubject: 处理请求");
  }
}

class ProxySubject implements Subject {
  private realSubject: RealSubject;

  constructor() {
    this.realSubject = new RealSubject();
  }

  request(): void {
    console.log("Proxy: 进行额外的操作(如日志记录、权限控制等)");
    this.realSubject.request();
  }
}

const proxy = new ProxySubject();
proxy.request();

2.2 动态代理

动态代理通常使用 Proxy 对象,它能在运行时动态地拦截对目标对象的操作。

const target = {
  message: "Hello, World!",
  greet(name: string) {
    return `Hello, ${name}`;
  },
};

const handler: ProxyHandler<typeof target> = {
  get(target, prop, receiver) {
    console.log(`访问属性: ${String(prop)}`);
    return Reflect.get(target, prop, receiver);
  },
  set(target, prop, value, receiver) {
    console.log(`设置属性: ${String(prop)} = ${value}`);
    return Reflect.set(target, prop, value, receiver);
  },
};

const proxyObj = new Proxy(target, handler);
console.log(proxyObj.message);
proxyObj.message = "Hello, Proxy!";
console.log(proxyObj.greet("Alice"));

3. 代理模式的应用场景

3.1 缓存代理

在某些情况下,我们可以使用代理模式来缓存计算结果,以提高性能。

class ExpensiveOperation {
  compute(value: number): number {
    console.log(`执行计算: ${value} * ${value}`);
    return value * value;
  }
}

class CachedProxy {
  private realSubject: ExpensiveOperation;
  private cache: Map<number, number>;

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

  compute(value: number): number {
    if (this.cache.has(value)) {
      console.log("从缓存中获取结果");
      return this.cache.get(value)!;
    }
    const result = this.realSubject.compute(value);
    this.cache.set(value, result);
    return result;
  }
}

const proxyCache = new CachedProxy();
console.log(proxyCache.compute(5));
console.log(proxyCache.compute(5));

3.2 访问控制代理

对于某些敏感操作,我们可以使用代理模式来限制访问。

class SecureData {
  getSecret(): string {
    return "敏感数据";
  }
}

class SecurityProxy {
  private realSubject: SecureData;
  private userRole: string;

  constructor(userRole: string) {
    this.realSubject = new SecureData();
    this.userRole = userRole;
  }

  getSecret(): string {
    if (this.userRole !== "admin") {
      throw new Error("权限不足,无法访问数据");
    }
    return this.realSubject.getSecret();
  }
}

try {
  const secureProxy = new SecurityProxy("guest");
  console.log(secureProxy.getSecret());
} catch (error) {
  console.error(error.message);
}

4. 总结

代理模式在 TypeScript 开发中有着广泛的应用,尤其是动态代理,它提供了一种灵活的方式来增强对象的功能,例如日志记录、缓存、访问控制等。在实际开发中,可以根据需求选择合适的代理模式,提高代码的可维护性和扩展性。

<-TypeScript设计模式(5):观察者模式