美文网首页
第十三章 职责链模式

第十三章 职责链模式

作者: 狐尼克朱迪 | 来源:发表于2016-09-28 15:56 被阅读0次

    职责链模式的定义是: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象形成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

    举一个实际的例子:一款新手机发布会后,经过了缴纳过500元定金和200元定金的两轮预售后,现在到了正式购买的阶段。 厂家对交付过定金的用户有一定的优惠政策:缴纳500的用户,会得到一张100元的优惠券;缴纳200的用户,会得到一张30元的优惠券;没有交付定金的用户,没有优惠券,只能进入普通购买模式,而且在库存有限的情况下,不一定能买得到。

    具体的程序实现如下:

        var order = function(orderType, pay, stock){
            if(orderType == 1){ // 500元定金模式
                if(pay){
                    console.log("500元定金, 得到100优惠券");
                }else{
                    if(stock > 0){ // 还有库存
                        console.log("普通购买 无优惠券");
                    }else{
                        console.log("手机库存不足");
                    }
                }
            }else if(orderType == 2){ // 100元定金模式
                if(pay){
                    console.log("200元定金, 得到30优惠券");
                }else{
                    if(stock > 0){ // 还有库存
                        console.log("普通购买 无优惠券");
                    }else{
                        console.log("手机库存不足");
                    }
                }
            }else if(orderType == 3){ // 无定金模式
                if(stock > 0){ // 还有库存
                    console.log("普通购买 无优惠券");
                }else{
                    console.log("手机库存不足");
                }
            }
        }
    

    上面的程序难以阅读而且如要进行修改,工作量会很大。切合本章的主题,我们引入职责链模式:

        // 500定金
        var order500 = function(orderType, pay, stock){
            if(orderType == 1 && pay){
                console.log("500元定金, 得到100优惠券");
            }else{
                order200(orderType, pay, stock); // 此处order500 和 order200的耦合
            }
        }
        
        // 200定金
        var order200 = function(orderType, pay, stock){
            if(orderType == 2 && pay){
                console.log("200元定金, 得到30优惠券");
            }else{
                orderNromal(orderType, pay, stock);// 此处orderNromal 和 order200的耦合
            }
        }
        
        // 普通
        var orderNromal = function(orderType, pay, stock){
            if(stock > 0){ // 还有库存
                    console.log("普通购买 无优惠券");
            }else{
                console.log("手机库存不足");
            }
        }
    

    通过这种形式个改造,整个程序结构就清晰很多。但是其中还是有耦合的问题,例如如果加一个300定金的情况,那么order500 order200都需要进行相应逻辑的修改。为此我们进一步进行程序的优化:

        // 500定金
        var order500 = function(orderType, pay, stock){
            if(orderType == 1 && pay){
                console.log("500元定金, 得到100优惠券");
            }else{
                return 'nextSuccessor';
            }
        }
        
        // 200定金
        var order200 = function(orderType, pay, stock){
            if(orderType == 2 && pay){
                console.log("200元定金, 得到30优惠券");
            }else{
                return 'nextSuccessor';
            }
        }
        
        // 普通
        var orderNromal = function(orderType, pay, stock){
            if(stock > 0){ // 还有库存
                    console.log("普通购买 无优惠券");
            }else{
                console.log("手机库存不足");
            }
        }
        
        // 构造函数chain
        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;
        }
        
        // 把三个包装城职责链的节点
        var chainOrder500 = new Chain(order500);
        var chainOrder200 = new Chain(order200);
        var chainOrderNromal = new Chain(orderNromal);
    
        // 制定职责链中顺序
        chainOrder500.setNextSuccessor(chainOrder200);
        chainOrder200.setNextSuccessor(chainOrderNromal);
        
        // 如下是执行
        chainOrder500.passRequest(1, true, 500); // 500元定金, 得到100优惠券
        chainOrder500.passRequest(2, true, 500); // 200元定金, 得到30优惠券
        
        
        // 借助AOP,可以把上面的Chain改成更为方便的形式
        Function.prototype.after = function( fn ){
            var self = this;
            return function(){
                var ret = self.apply(this, arguments);
                if(ret == 'nextSuccessor'){
                    return fn.apply(this, arguments);
                }
                return ret;
            }
        }
        
        var order = order500.after(order200).after(orderNormal);
    

    职责链模式一方面更加清晰的组织我们的代码;还可以灵活地拆分重组节点对象;另外可以手动设定起始节点,因为请求并不一定从最前面一个节点开始(比如一个挤满人的公交车,你从后门上车,把钱传递给售票员,你的终点是固定的,但是你并不能确定谁是第一个接到你钱的人)。 唯一的问题是,要保证链不能太长,要不会引发性能问题。

    采用aop实现职责链是一个非常好的形式~

    异步职责链

    如果是异步的话,那么直接返回"nextSuccessor"就没什么意义了,所以需要给Chain类再增加一个原型方法:Chain.prototype.next,表示手动传递请求给职责链中的下一个节点:

    var Chain = function( fn ){
        this.fn = fn;
        this.successor = null;
    }
    
    Chain.prototype.setNextSuccessor = function( successor ){
        return this.successor = successor;
    }
    
    Chain.prototype.next = function(){
        return this.successor && this.successor.passRequest.apply(this.successor, arguments);
    }
    
    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;
    }
    
    
    var fn1 = new Chain(function(){
        console.log(1);
        return 'nextSuccessor';
    });
    var fn2 = new Chain(function(){
        console.log(2);
        var self = this;
        setTimeout(function(){
            self.next();
        }, 1000);
    });
    var fn3 = new Chain(function(){
        console.log(3);
    })
    
    fn1.setNextSuccessor(fn2).setNextSuccessor(fn3);
    fn1.passRequest();
    

    相关文章

      网友评论

          本文标题:第十三章 职责链模式

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