美文网首页
职责链模式

职责链模式

作者: 小宇cool | 来源:发表于2020-11-06 21:18 被阅读0次

    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);// 移交董事长处理
    
    

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

    相关文章

      网友评论

          本文标题:职责链模式

          本文链接:https://www.haomeiwen.com/subject/eqsxbktx.html