zoukankan      html  css  js  c++  java
  • 职责链模式

    简介

    职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。 也就是说,请求以后,从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者。提交请求的对象并不明确知道哪一个对象将会处理它——也就是该请求有一个隐式的接受者(implicit receiver)。根据运行时刻,任一候选者都可以响应相应的请求,候选者的数目是任意的,你可以在运行时刻决定哪些候选者参与到链中。

    案例一

    果伯伯在水果市场卖苹果,果果老板说:苹果分优质,中等,一般,给钱就卖四大类苹果。
    优质苹果5元一斤,中等苹果4元一斤,一般苹果3元一斤,给钱就卖苹果1元一斤,一次最少卖一斤(这是例子,现实中不是这样的)
    小明拿5元钱在这个摊上买1斤苹果,
    小亮拿4元钱也在这个摊上买1斤苹果,
    小帅拿3元钱也在这个摊上买1斤苹果,
    小七拿1元钱也在这个摊上买1斤苹果,

    分析: 小明、小亮、小帅、小七都是拿钱去买苹果的,他们就好比【一个个的请求】; 果伯伯的摊位就可以当做一个职责链,处理不同的买方请求。 苹果价位:price=5,4,3,1, 小明、小亮、小帅、小七的钱:people$=5,4,3,1

    第一个版本:

    /**
     * 买苹果
     * @name {string} 姓名
     * @price {Number} 价格
     * @weight {Number} 重量
     * 
     * */
    function buyapple(name,price,weight){
        if(price==5){
            console.log(name+'买到了5元1斤的苹果');
        }else if(price==4){
            console.log(name+'买到了4元1斤的苹果');
        }else if(price==3){
            console.log(name+'买到了3元1斤的苹果');
        }else if(price==1){
            console.log(name+'买到了1元1斤的苹果');
        }
    }
    buyapple('小明',5,1);
    buyapple('小亮',4,1);
    buyapple('小帅',3,1);
    buyapple('小七',1,1);

    上述代码也许是最简单代码,最初级的程序员都会写,但是这样写的代码if嵌套比较多,更改维护比较费劲。假设又有2元一斤的苹果与用户,那就需要更改源码了。

    第二个版本:

    function buyapple5(name,price,weight){
        if(price==5){
           console.log(name+'买到了5元1斤的苹果');
        }else{
            return 'next';
        }
    }
    function buyapple4(name,price,weight){
        if(price==4){
           console.log(name+'买到了4元1斤的苹果');
        }else{
            return 'next';
        }
    }
    function buyapple3(name,price,weight){
        if(price==3){
           console.log(name+'买到了3元1斤的苹果');
        }else{
            return 'next';
        }
    }
    function buyapple1(name,price,weight){
        if(price==1){
           console.log(name+'买到了1元1斤的苹果');
        }else{
            return 'next';
        }
    }
    
    function Buyapple(fn){
        this.fn=fn;
        this.nextfn=null;//把下一个执行设置为null
    }
    Buyapple.prototype.setNextfn=function(nextfn){
        return this.nextfn=nextfn;//设置下一个执行的函数
    }
    Buyapple.prototype.Nextfn=function(){
       var res = this.fn.apply(this,arguments);//执行当前函数  
       if( res === "next" ){  
            //判断当前函数是否有下一个执行函数,有则执行
          return this.nextfn && this.nextfn.Nextfn.apply(this.nextfn,arguments);  
       }  
    }
    
    //现在我们吧3个订单函数分别包装成职责链的节点  
    var chainOrder5 = new Buyapple(buyapple5);  
    var chainOrder4 = new Buyapple(buyapple4); 
    var chainOrder3 = new Buyapple(buyapple3)
    var chainOrder1 = new Buyapple(buyapple1);  
    //然后指定节点在指责链的顺序  
    chainOrder5.setNextfn(chainOrder4);  
    chainOrder4.setNextfn(chainOrder3);
    chainOrder3.setNextfn(chainOrder1);
    //最后传递请求  最上层,过滤数据执行
    chainOrder5.Nextfn('小帅',3,1);

    目前的职责链能够保证按照顺序执行下去。可以随意组合。但现在的代码只能保证是同步执行的。如果有异步中间执行代码则无法执行。

    第三个版本:

    function buyapple5(name,price,weight){
        if(price==5){
           console.log(name+'买到了5元1斤的苹果');
        }else{
            return 'next';
        }
    }
    function buyapple4(name,price,weight){
        var that=this;
        if(price==4){
           console.log(name+'买到了4元1斤的苹果');
        }
        setTimeout(function(){
            console.log('等待两秒后执行');
            that.next(name,price,weight);
        },2000);
    
    }
    function buyapple3(name,price,weight){
        if(price==3){
           console.log(name+'买到了3元1斤的苹果');
        }else{
            return 'next';
        }
    }
    function buyapple1(name,price,weight){
        if(price==1){
           console.log(name+'买到了1元1斤的苹果');
        }else{
            return 'next';
        }
    }
    
    function Buyapple(fn){
        this.fn=fn;
        this.nextfn=null;//把下一个执行设置为null
    }
    Buyapple.prototype.setNextfn=function(nextfn){
        return this.nextfn=nextfn;//设置下一个执行的函数
    }
    Buyapple.prototype.Nextfn=function(){
       var res = this.fn.apply(this,arguments);//执行当前函数  
       if( res === "next" ){  
            //判断当前函数是否有下一个执行函数,有则执行
          return this.nextfn && this.nextfn.Nextfn.apply(this.nextfn,arguments);  
       }  
    }
    Buyapple.prototype.next=function(){
            //异步函数是无法返回next,只有借助next函数触发执行
          return this.nextfn && this.nextfn.Nextfn.apply(this.nextfn,arguments);  
    }
    //现在我们吧3个订单函数分别包装成职责链的节点  
    var chainOrder5 = new Buyapple(buyapple5);  
    var chainOrder4 = new Buyapple(buyapple4); 
    var chainOrder3 = new Buyapple(buyapple3)
    var chainOrder1 = new Buyapple(buyapple1);  
    //然后指定节点在指责链的顺序  
    chainOrder5.setNextfn(chainOrder4);  
    chainOrder4.setNextfn(chainOrder3);
    chainOrder3.setNextfn(chainOrder1);
    //最后传递请求  最上层,过滤数据执行
    chainOrder5.Nextfn('小帅',3,1);

    connect框架next函数

    var i=0,//索引
    _arrycallback=[];//存储函数
    //执行下一个函数
    function next(){
        i++;
        _arrycallback[i] && _arrycallback[i]();
    }
    //存储next函数
    function push_next(fn){
        _arrycallback.push(fn);
    };
    
    push_next(function(){
        console.log("1");
        next();
    });
    push_next(function(){
        setTimeout(function(){
            console.log("2","延迟500毫秒输出");
            next();
        },3000)
    
    });
    push_next(function(){
        console.log("3");
        next();
    });
    push_next(function(){
        console.log("4");
        next();
    });
    //执行
    _arrycallback[0]();

    Node.js 中大名鼎鼎的connect框架正是这样实现中间件队列的。有兴趣可以去看看它的源码或者这篇解读《何为 connect 中间件》。

    总结

    一:职责链模式的最大优点就是解耦了请求必送者和N个接收者之间的复杂关系,由于不知道链中的如个节点可以处理你发现的请求,所以你只需要请求传递给第一个节点即可。
    二:使用了职责链模式之后,链中的节点对象可以灵活地拆分重组。增加或者删除一个节点,或者改变节点在链中的位置都是轻而易举的事情。
    三:在职责模式还有一个优点,那就是可以手动指定起始节点,请求并不是非得从链中的第一个节点开始传递。
    四:职责链模式使得程序中多了一些节点对象,可能在某一次的请求过程中,大部分节点并没有起到实质性的作用,它们的作用仅仅是让请求传递下去,从性能方面考虑,我们要避免过长的职责链带来性能损耗。
    五:如果一个节点出错,就会导致整个链条断开。

  • 相关阅读:
    找出2n+1个数中不成对的那个(升级版)
    找出2n+1个数中不成对的那个
    随手记,完美的记账软件
    NOD32强制卸载工具使用方法【转】
    中医养生重在养“气”【灵枢针灸-袁医生】
    美国大学对本科生培养的12条标准【转】
    Windows软件使用Q&A集锦【持续更新】
    VLSI和ASIC的区别(转)
    Verilog 模块参数重定义(转)
    FPGA技术的一些基本概念(综合、BlackBox)(转)
  • 原文地址:https://www.cnblogs.com/xiaoxiaokun/p/7650091.html
Copyright © 2011-2022 走看看