设计模式-责任链模式

22 阅读1分钟

定义

责任链模式,是一种行为设计模式,它允许你将请求沿着处理者链传递,直到某个处理者负责处理该请求。

这种模式让多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。

UML 类图

typescript 实现

1. 定义处理器接口

interface Handler {
  setNext(h: Handler): void;
  handle(request: any): any;
}

2. 基础处理器实现

class BaseHandler implements Handler {
  private next: Handler | null = null;

  setNext(h: Handler) {
    this.next = handler;
    return handler;
  }
  public handle(request: any): any {
    if(this.next) {
      return this.next.handle(request);
    }
    return null;
  }
}

3. 创建具体处理者

class ConcreteHandler1 extends BaseHandler {
  public handle(request: any): any {
    if(request === "A") {
      return `ConcreteHandler handled request ${request}`);
    } else {
      return super.handle(request);
    }
  }
}

class ConcreteHandler2 extends BaseHandler {
  public handle(request: any): any {
    if(request === "B") {
      return `ConcreteHandler2 handled request ${request}`;
    } else {
      return super.handle(request);
    }
  }
}

class DefaultHandler extends BaseHandler {
  public handle(request: any): any {
    return `DefaultHandler handled request ${requset}`;
  }
}

4. 使用示例

function clientCode(handler: Handler) {
  const requests = ["A", "B", "C"];
  for(const request of requests) {
    console.log(`Client: Who can handle ${request}`);
    const result = handler.handle(request);
    if(result) {
      console.log(` ${result}`);
    } else {
      console.log(` ${request} was left unhandled.`);
    }
  }
}

// 组装责任链
const handler1 = new ConcreteHandler1();
const handler2 = new ConcreteHandler2();
const defaultHanlder = new DefaultHandler();

handler1.setNext(handler2).setNext(defaultHandler);
clientCode(handler1);

通用实现

// 公共代码
export abstract class ChainHandler<T> {
  protected next: ChainHandler<T> | null = null;
  public setNext(handler: ChainHandler<T>): ChainHandler<T> {
    this.next = handler;
    return handler;
  }
  public handle(arg: T): any | null {
    if(this.next) {
      return this.next.handle(arg);
    }
    return null;
  }
}

// 私有代码,URL 类
class URL {
  constructor(url: string) {
    this.url = url;
  }
}

// 私有代码,各种 Filter
class TxtFilter extends ChainHandler<URL> {
  handle(arg: URL): any {
    if(arg.url.endsWith("txt")) {
      return true;
    } else {
      return super.handle(arg);
    }
  }
}

class ImgFilter extends ChainHandler<URL> {
  handle(arg: URL): any {
    if(arg.url.endsWith("png")) {
      return true;
    } else {
      return super.handle(arg);
    }
  }
}

class DefaultFilter extends ChainHandler<URL> {
  handle(arg: URL): any {
    return false;
  }
}

// 私有代码,使用示例
const txtFilter = new TxtFilter();
const imgFilter = new ImgFilter();
const defaultFilter = new DefaultFilter();

txtFilter.setNext(imgFilter).setNext(defaultFilter);
const boolean = txtFilter.handle(new URL("https://flywen.top/demo.txt"));
console.log(boolean);