设计模式-代理模式

24 阅读1分钟

定义

代理模式,是一种结构型设计模式,它提供了对另外一个对象的代理或占位符,以控制对这个对象的访问。

使用代理模式可以在不改变被代理对象的前提下,为客户端和被代理对象之间提供一个中介,并进行一些操作,如访问控制,延迟初始化,日志等。

UML 类图

typescript 实现

1. 定义主题接口

interface Subject {
  operation(): void;
}

2. 创建真实主题类

class RealSubject implements Subject {
  public operation(): void {
    console.log("RealSubject: Handling operation.");
  }
}

3. 创建代理类

class Proxy implements Subject {
  private realSubject: RealSubject;
  constructor(realSubject: RealSubject) {
    this.realSubject = realSubject;
  }
  public operation(): void {
    if(this.checkAccess()) {
      this.realSubject.operation();
      this.logAccess();
    }
  }
  private checkAccess(): boolean {
    console.log('Proxy: Checking access before firing a real operation.');
    return true;
  }
  private logAccess(): void {
    console.log('Proxy: Logging the time of operation.');
  }
}

4. 使用示例

function clientCode(subject: Subject) {
  subject.operation();
}

console.log("Client: Executing the client code with a real subject:");
const realSubject = new RealSubject();
clientCode(realSubject);

console.log("");

console.log("Client: Executing the same client code with a proxy:");
const proxy = new Proxy(realSubject);
clientCode(proxy);

通用实现

// 公共代码,缓存代理
export function createCacheProxyFactory<T extends (...args: any[]) => any>(fn: T): T {
  const cache = new Map<string, any>();
  const isProxySupported = () => {
    return typeof Proxy !== 'undefined';
  }
  if(isProxySupported()) {
    return new Proxy(fn, {
      apply(target: T, thisArg, args: any[]) {
        const key = JSON.stringify(args);
        if(cache.has(key)) {
          return cache.get(key);
        } else {
          const result = Reflect.apply(target, thisArg, args);
          cache.set(key, result);
          return result;
        }
      }
    })
  } else {
    return function(...args: any[]) {
      const key = JSON.stringify(args);
      if(cache.has(key)) {
        return cache.get(key);
      } else {
        const result = fn(...args);
        cache.set(key, result);
        return result;
      }
    } as T;
  }
}

// 私有代码,使用示例
// 这个函数计算比较耗时,我们对此进行暂存计算结果
const expensiveFunction = (arg: number) => {
  return arg * 100;
}
const cachedExpensiveFunction = createCahceProxyFactory(expensiveFunction);
cachedExpensiveFunction(5);