> For the complete documentation index, see [llms.txt](https://xyy94813.gitbook.io/x-note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xyy94813.gitbook.io/x-note/she-ji-mo-shi/chang-jian-she-ji-mo-shi/chain-of-responsibility.md).

# 责任链模式

责任链模式，允许将请求沿着处理者链进行发送。收到请求后，每个处理者均可对请求进行处理，或将其传递给链上的下个处理者。

拦截器、中间件就是典型的责任链模式

## 适用场景

* 当程序需要使用不同方式处理不同种类请求，而且请求类型和顺序预先未知时，可以使用责任链模式。
* 当必须按顺序执行多个处理者时，可以使用该模式。
* 如果所需处理者及其顺序必须在运行时进行改变，可以使用责任链模式。

## 优/缺点

优点：

* 你可以控制请求处理的顺序
* 单一职责原则。你可对发起操作和执行操作的类进行解耦。
* 开闭原则。你可以在不更改现有代码的情况下在程序中新增处理者。

缺点：

* 部分请求可能未被处理

## 对比其他模式

* 责任链模式、命令模式、中介者模式和观察者模式用于处理请求发送者和接收者之间的不同连接方式：
  * 责任链按照顺序将请求动态传递给一系列的潜在接收者，直至其中一名接收者对请求进行处理。
  * 命令在发送者和请求者之间建立单向连接。
  * 中介者清除了发送者和请求者之间的直接连接，强制它们通过一个中介对象进行间接沟通。
  * 观察者允许接收者动态地订阅或取消接收请求。
* 责任链通常和组合模式结合使用。在这种情况下，叶组件接收到请求后，可以将请求沿包含全体父组件的链一直传递至对象树的底部。
* 责任链的管理者可使用命令模式实现。在这种情况下，你可以对由请求代表的同一个上下文对象执行许多不同的操作。
* 责任链和装饰模式的类结构非常相似。两者都依赖递归组合将需要执行的操作传递给一系列对象。但是，两者有几点重要的不同之处。 责任链的管理者可以相互独立地执行一切操作，还可以随时停止传递请求。

## 实现示例

```ts
type Middleware = (ctx: any, next: Middleware) => {};

const compose = (middlewares: Middleware[]) => {
  const dispatch = (ctx: any, index: number) => {
    const cur = middlewares[index];
    if (!cur) return ctx;

    const next = (ctx: any) => dispatch(ctx, index + 1);

    return cur(ctx, next);
  };
  return (ctx) => dispatch(ctx, 0);
};

function main() {
  const client = compose([
    logMiddleware,
    authMiddleware,
    cacheMiddleware, //
    fetch,
  ]);

  const res = client(req);
}
```
