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

    1.职责链模式的定义是:使多个对象都有机会处理请求,从⽽避免请求的发送者和接收者之间的耦合关系,

    将这些对象连成⼀条链,并沿着这条链传递该请求,直到有⼀个对象处理它为⽌。 职责链模式的名字⾮
    常形象,⼀系列可能会处理请求的对象被连接成⼀条链,请求在这些对 象之间依次传递,直到遇到⼀个
    可以处理它的对象,我们把这些对象称为链中的节点
     
    假设我们负责⼀个售卖⼿机的电商⽹站,经过分别交纳 500 元定⾦和 200 元定⾦的两轮预定后(订单已
    在此时⽣成),现在已经到了正式购买的阶段。 公司针对⽀付过定⾦的⽤户有⼀定的优惠政策。在正式
    购买后,已经⽀付过 500 元定⾦的⽤ 户会收到 100 元的商城优惠券,200 元定⾦的⽤户可以收到 50 元
    的优惠券,⽽之前没有⽀付定⾦的⽤户只能进⼊普通购买模式,也就是没有优惠券,且在库存有限的情
    况下不⼀定保证能买到。
     
    var order = function( orderType, pay, stock ){
    if ( orderType === 1 ){ // 500 元定⾦购买模式
    if ( pay === true ){ // 已⽀付定⾦
    console.log( '500 元定⾦预购, 得到 100 优惠券' );
    } else{ // 未⽀付定⾦,降级到普通购买模式
    if ( stock > 0 ){ // ⽤于普通购买的⼿机还有库存
    console.log( '普通购买, ⽆优惠券' );
    }else{
    console.log( '⼿机库存不⾜' );
    }
    }
    } else if ( orderType === 2 ){
    if ( pay === true ){ // 200 元定⾦购买模式
    console.log( '200 元定⾦预购, 得到 50 优惠券' );
    }else{
    if ( stock > 0 ){
    console.log( '普通购买, ⽆优惠券' );
    }else{
    console.log( '⼿机库存不⾜' );
    }
    }
    } else if (orderType === 3) {
    if ( stock > 0 ){
    console.log( '普通购买, ⽆优惠券' );
    } else{
    console.log( '⼿机库存不⾜' );
    }
    }
    };
    order( 1 , true, 500); // 输出: 500 元定⾦预购, 得到 100 优惠券
     
    现在我们采⽤职责链模式重构这段代码,先把 500 元订单、200 元订单以及普通购买分成 3 个函数。
    接下来把 orderType、pay、stock 这 3 个字段当作参数传递给 500 元订单函数,如果该函数不符合处
    理条件,则把这个请求传递给后⾯的 200 元订单函数,如果 200 元订单函数依然不能处理该请求,则
    继续传递请求给普通购买函数。
     
    var order500 = function( orderType, pay, stock ){
    if ( orderType === 1 && pay === true ){
    console.log( '500 元定⾦预购,得到 100 优惠券' );
    } else{
    return 'nextSuccessor'; // 我不知道下⼀个节点是谁,反正把请求往后⾯传递
    }
    };
    var order200 = function( orderType, pay, stock ){
    if ( orderType === 2 && pay === true ){
    console.log( '200 元定⾦预购,得到 50 优惠券' );
    } else{
    return 'nextSuccessor'; // 我不知道下⼀个节点是谁,反正把请求往后⾯传递
    }
    };
    var orderNormal = function( orderType, pay, stock ){
    if ( stock > 0 ){
    console.log( '普通购买,⽆优惠券' );
    } else{
    console.log( '⼿机库存不⾜' );
    }
    };
    // Chain.prototype.setNextSuccessor 指定在链中的下⼀个节点
    // Chain.prototype.passRequest 传递请求给某个节点
    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 chainOrderNormal = new Chain( orderNormal );
    chainOrder500.setNextSuccessor( chainOrder200 );
    chainOrder200.setNextSuccessor( chainOrderNormal);
    chainOrder500.passRequest( 1, true, 500 ); // 输出:500 元定⾦预购,得到 100 优惠
    chainOrder500.passRequest( 2, true, 500 ); // 输出:200 元定⾦预购,得到 50 优惠券开课吧web全栈架构师
    chainOrder500.passRequest( 3, true, 500 ); // 输出:普通购买,⽆优惠券
    chainOrder500.passRequest( 1, false, 0 ); // 输出:⼿机库存不⾜
    通过改进,我们可以⾃由灵活地增加
    加、移除和修改链中的节点顺序,假如某天⽹站运营⼈员 ⼜想出了⽀
    持 300 元定⾦购买,那我们就在该链中增加⼀个节点即可
    var order300 = function(){
    // 具体实现略
    };
    chainOrder300= new Chain( order300 );
    chainOrder500.setNextSuccessor( chainOrder300);
    chainOrder300.setNextSuccessor( chainOrder200);
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    celery
    KeyError: 'pass_ticket'
    Go语言标准库之context
    Go语言标准库之log
    Go语言标准库之time
    Go语言基础之Cookie和Session
    #if...#endif的用法总结
    汇总#pragma用法
    Linux串口编程(转载)
    Linux系统调用(转载)
  • 原文地址:https://www.cnblogs.com/zhouyideboke/p/13666442.html
Copyright © 2011-2022 走看看