职责链模式
职责链是一种典型的 行为 型设计模式,核心在于链。
比方
- 一公司有 3 个程序员 小A、小B、小C
- 一天产品经理有一个新需求,他不清楚这需求由谁来负责
- 于是找到小 A。
    - 小 A 说这事不归我管,你问问小 B 吧
 
- 产品经理又找到了小 B
    - 小 B 说这一块也不归我,你问问小 C
 
- 小 C 接下了这个需求
一个任务从 A 转到 B,从 B 转到 C,再由 C 最终处理,形成了一个完整的任务处理链条
面对一个新任务,每个任务处理者需要判断自己能否处理该任务,如果能处理,则处理并返回;如果不能处理,则转交给下一个任务处理者,直到某一个处理者最终完成处理。这就是职责链模式核心思想
在职责链模式中,小 A 小 B 小 C 这样的任务处理者被称为 Handler
产品经理的角色则是 Client 的角色
应用场景
- 职责链有些像数据结构中的链表
- 职责链可以对每个任务进行部分处理,直到最后才吧任务处理完毕
    - 若干个过滤器组成一个职责链,每一个过滤器过滤一部分非法内容
 
UML
实现
每一个具体 Handler 类都继承自统一的抽象类
- Handle 对象包含一个 successor 成员,指向它的下一个任务处理者(链表节点的 next 指针)
abstract public class Handler {
    protected Handler successor;
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    abstract String handleRequest(String msg);
}
实现三个具体的 Handler 类,用于替换吧某一个字符替换成*
public class HandlerA extends Handler {
    @Override
    String handleRequest(String msg) {
        if(msg.contains("a")){
            msg = msg.replace('a', '*');
        } else if(this.successor != null){
            msg = this.successor.handleRequest(msg);
        }
        return msg;
    }
}
public class HandlerB extends Handler {
    @Override
    String handleRequest(String msg) {
        if(msg.contains("b")){
            msg = msg.replace('b', '*');
        } else if(this.successor != null){
            msg = this.successor.handleRequest(msg);
        }
        return msg;
    }
}
public class HandlerC extends Handler {
    @Override
    String handleRequest(String msg) {
        if(msg.contains("c")){
            msg = msg.replace('c', '*');
        } else if(this.successor != null){
            msg = this.successor.handleRequest(msg);
        }
        return msg;
    }
}
public class Client {
    public static void main(String[] args) {
        Handler handlerA = new HandlerA();
        Handler handlerB = new HandlerB();
        Handler handlerC = new HandlerC();
        handlerA.setSuccessor(handlerB);
        handlerB.setSuccessor(handlerC);
        System.out.println(handlerA.handleRequest("apple"));
        System.out.println(handlerA.handleRequest("bicycle"));
        System.out.println(handlerA.handleRequest("color"));
    }
}
职责链的缺点
- Debug 不友好,链路深的时候需压调试很多层
框架中的应用
- Tomcat 容器中的过滤器 Filter
    - 过滤器针对请求的访问、参数合法性等方面进行验证和过滤
 
- SpringMVC 中的拦截器
    - 客户端 HTTP 请求到了 Web 应用之后,会被 SpringMVC 框架中的 DisapatcherServlet 类进行分发给 Controller 层具体方法
- 在进入 Controller 层业务逻辑之前、以及执行完逻辑之后都会经过一系列的拦截器 Interceptor
 
Javascript 职责链
var order01 = function () {
  console.log(1);
  return "nextSuccessor";
};
var order02 = function () {
  console.log(2);
  var self = this;
  setTimeout(function () {
    self.next();
  }, 1000);
};
var order03 = function () {
  console.log(3);
};
var Chain = function (fn) {
  this.fn = fn;
  this.successor = null;
};
Chain.prototype.setNextSuccessor = function (successor) {
  //指定在链中的下一个节点
  return (this.successor = successor);
};
Chain.prototype.passRequest = function () {
  //传递请求给某个节点
  var ret = this.fn.apply(this, arguments);
  if (ret === "nextSuccessor") {
    return (
      this.successor &&
      this.successor.passRequest.apply(this.successor, arguments)
    );
  }
  return ret;
};
Chain.prototype.next = function () {
  return (
    this.successor &&
    this.successor.passRequest.apply(this.successor, arguments)
  );
};
//      现在我们把 3个订单函数分别包装成职责链的节点:
var fn1 = new Chain(order01);
var fn2 = new Chain(order02);
var fn3 = new Chain(order03);
//      然后指定节点在职责链中的顺序:
fn1.setNextSuccessor(fn2).setNextSuccessor(fn3);
//      最后把请求传递给第一个节点:
fn1.passRequest();
参见