阅读 100

职责链模式

1. 职责链模式

1.1 定义:

​ 职责链模式(Chain of responsibility):是使多个对象都有机会处理请求, 从而避免请求的发送者和接受者之间的耦合关系.将这些对象练成一条链, 并言者这条链传递请求, 直到有一个对象处理它为止.

JavaScript中的作用域链,原型链都是基于职责链模式,都是沿着链一直直到找到为止,职责链就是要搭建这样一个结构,一层一层的传递请求直到处理了为止.

1.2 作用

  1. 较低耦合度, 它将请求的发送者和接受者解耦.
  2. 简化了对象. 增强了给对象指派职责的灵活性.允许动态的新增或者删除职责
  3. 增加新的请求处理类会很方便.

1.3 应用场景

情景: 要提交一个申购申请, 小于100000, 部门负责人处理, 大于100000小于50000, 院负责人处理;大于50000小于1000000群负责人处理, 大于100000, 董事长处理.

我们按照平常的写法

  function request(value){
      if(value <= 10000){
          console.log('移交部门负责人处理');
          // code...
      }else if(value <= 50000){
          console.log('移交院负责人处理')
          // code...
      }else if(value <= 100000){
          console.log('移交群负责人处理')
          // code...
      }else if(value > 100000){
          console.log('移交董事长处理')
          // code...
      }
  }
request(20000) // 移交院负责人处理

上面的代码需求虽然可以解决, 但是if...else的代码结构有点麻烦,不是很优雅,如果需要修改每个分支或者新添加的时候, 必须修改整个request函数,违反了开闭原则, 我们可以使用职责链模式来改写一下代码.

//将每个分支结构分离:
function director01(value){
    if( value <= 10000 ){
        console.log("移交部门负责人处理。");
        // code……
    }else{
        //移交给下一个处理人
        director02(value);
    }
}
function director02(value){
    if( value <= 50000 ){
        console.log("移交院负责人处理。");
       // code……
    }else{
        //移交给下一个处理人
        director03(value);
    }
}
function director03(value){
    if( value <= 100000 ){
        console.log("移交群负责人处理。");
      // code……
    }else{
        //移交给下一个处理人
        director04(value);
    }
}
function director04(value){
    if( value > 100000 ){
        console.log("移交董事长处理。");
        // code……
    }
}

//只需要从第一个处理人开始
director01(20000);

现在我们通过职责链模式将结构的每个分支分开, 耦合度比上面的写法要好很多.但是每个处理层必须强关联下一个处理层,不然就没办法链式调用, 这又是一个很严重的问题, 层层之间的耦合还是很高, 假设要添加下一个处理层. 那么要改的地方就有上下两处. 非常麻烦, 我们可以将代码继续修改并优化一下

  //只需要从第一个处理人开始
class Chain{
    constructor(){
        // 当前职责链的长度
        this.length = 0;
        // 保存当前职责链
        this.successor = [];
    }
    setSuccessor(...rest){
        this.length = rest.length;
        this.successor = rest
    }
    request(...rest){
        // 第一种写法
        // 利用自执行函数传递index绑定函数上下文 index->指向当前职责链的位置
        (function dispose(index){
            // 判断index 是否在职责链的范围内
            if(index > this.length) {
                return '无法处理'
            }
            // 通过index 获取对应的职责对象
            let result = this.successor[index](...rest);
            // 如果返回了next 就递归调用dispose 否者返回 result
            if(result === 'next'){
                index++;
                dispose.call(this,index)
            }else{
                return result
            }
        }).call(this,0);
        /*
            上面的利用函数递归 稍微有点麻烦,可以用如下的代码稍微简化一点
        */
        // 第二种写法 
        // 利用while循环遍历, 当result不为next是停止循环
        let index = 0,
            result = this.successor[index](...rest);
        while(result === 'next'){
             result = this.successor[++index](...rest);
          }
        return result
    }
}
//将每个分支结构分离:
function director01(value) {
    if (value <= 10000) {
        console.log("移交部门负责人处理。");
        //some code……
    } else {
        //无须再强关联下一个处理函数
        return "next";
    }
}
function director02(value) {
    if (value <= 50000) {
        console.log("移交院负责人处理。");
        //some code……
    } else {
        //无须再强关联下一个处理函数
        return "next";
    }
}
function director03(value) {
    if (value <= 100000) {
        console.log("移交群负责人处理。");
        //some code……
    } else {
        //无须再强关联下一个处理函数
        return "next";
    }
}
function director04(value) {
    if (value > 120000) {
        console.log("移交董事长处理。");
        //some code……
        return true
    }
}
  //实现链
let request = new Chain();
//设置处理队列
request.setSuccessor(
    director01,
    director02,
    director03,
    director04,
);
//调用
let res = request.request(120003);// 移交董事长处理

总结: 当有多个对象处理同一个请求时, 具体哪个对象处理该请求由运行时刻自动确定, 在不明确接受者的情况下, 使用 职责链模式非常合适, 职责链模式使得客户端只需要将请求发送到职责链上即可, 无需关心请求的处理细节和请求的传递, 职责链模式在内部将请求的方法者和请求的处理解耦了.

作者:小宇cool

原文链接:https://www.jianshu.com/p/93524d19d1d1

文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐