三分钟教会你JS设计模式之职责链模式

来源:http://www.chinese-glasses.com 作者:Web前端 人气:144 发布时间:2020-04-22
摘要:时间: 2019-09-22阅读: 97标签: 模式 职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请

时间: 2019-09-22阅读: 97标签: 模式

职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
职责链模式的名字非常形象,一系列可能会处理请求的对象被该连接成一条链,请求在这些对象之间依次传递,直到遇到一个可以处理它的对象,我们把这些对象成为链中的节点。

职责链模式是设计模式中行为型的一种设计模式;

现实中的职责链模式

定义:

挤公交车

10bet,高峰期挤上公交车必须一个个往前递钱让前面的人把钱交给售票员,最后才让售票员处理。

使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系,将这些处理请求的对象形成一个链,并沿着这个链传递请求,直到有一个对象处理它为止;

职责链的优点

请求发送者只需要知道链中的第一个节点,从而弱化了发送者和一组接收者之间的强联系。如果不使用职责链模式,那么在公交车上,必须先搞清楚谁是售票员,才能把硬币递给他。

白话解释:

开始实例开发

假设一个电视网站对于某部新上市的手机经过了2轮缴纳500元定金与200元定金的预定,现在已经到了正式购买的阶段。
支付了500元定金的用户在购买阶段可以使用100元优惠券,200元定金可以使用50元优惠券,普通用户没有如果没有库存不一定能买到。

订单页面时php模板,表单几个字段如下:

orderType: 表示订单类型(定金或者普通用户),code的值为1时候是500元定金用户,为2是200元定金用户,为3则是普通用户。

pay : 表示用户是否支付定金,用户虽然下过500元定金的订单但是如果他一直没有支付定金,那么只能降级为普通用户。

stock : 仅用户普通用户的库存数量,定金用户不受限制。

我们省略了使用普通代码进行开发的语句,因为实在太难看了太多的if语句,面向过程以后的维护工作恐怕是个梦魇。(其实是作者懒:)

作者坐标武汉,1000+万人口的新一线城市 ;以早高峰公交为例,早上早高峰的时候通常都是公交车前门拥堵,以至于没办法刷卡乘车;但是后门相对来说会空一些,这时我们选择后门上车,但是我们后门上车就刷不了卡;逃单?不存在的,这可不是我们作为讲文明、有素质的新一代青年应该做的;于是,我们往前面传递公交卡,请求前面的乘客帮忙传递至刷卡器处刷卡,但是我们是在后门,刷卡器是在前门,我们这传递的过程中会通过请求多位乘客帮忙传递公交卡,这个传递的过程就是一种职责链模式,每一位传递的乘客就是职责链中的节点对象;

职责链模式重构

参见代码:

      // 500 order
var order500 = function (orderType,pay,stock) {
if(orderType === 1 && pay === true){
     console.log('500 rmb deposit, get 100 coupon ')
} else {
     order100(orderType,pay,stock)  // req pass to 200 order
}
};

var order200 = function (orderType,pay,stock) {
if(orderType === 2 && pay === true){
    console.log('200 rmb deposit , get 50 coupon')
} else{
    orderNormal(orderType,pay,stock) 
}
};

var orderNormal = function (orderType,pay,stock) {
if(stock > 0){
     console.log('normal buy no coupon')
} else{
     console.log('the stock lack')
}
};

//test result:
order500(1,true,500);
order500(2,true,500);
order500(3,true,500);
order500(1,false,500);

现在已经基本符合了职责链模式定义,下面实现灵活可拆分的职责链模式,我的意思就是不要像上述那样面向过程的从500传递到200然后再到普通,万一我们想传递到100呢? 岂不是还得要大修一番?

参见修改后的代码:

 // 500 order
var order500 = function (orderType,pay,stock) {
if(orderType === 1 && pay === true){
     console.log('500 rmb deposit, get 100 coupon ')
} else {
    return 'nextSuccessor'  // unknow the next node but always pass to next.
}
};

var order200 = function (orderType,pay,stock) {
if(orderType === 2 && pay === true){
    console.log('200 rmb deposit , get 50 coupon')
} else{
    return 'nextSuccessor'; 
}
  };

var orderNormal = function (orderType,pay,stock) {
if(stock > 0){
     console.log('normal buy no coupon')
} else{
     console.log('the stock lack')
}
    };


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;
}

//现在我们把3个订单函数分别包装成职责链的节点
var chainOrder500 = new Chain(order500);
var chainOrder200 = new Chain(order200);
var chainOrderNormal = new Chain(orderNormal);

    //最后把请求传递给第一个节点
    chainOrder500.setNextSuccessor(chainOrder200)
    chainOrder200.setNextSuccessor(chainOrderNormal)

//最后把请求传递给第一个节点
//test
chainOrder500.passRequest(1,true,500);
chainOrder500.passRequest(2,true,500);

//通过改进,我们可以自由灵活的增加移除和链中的节点顺序,假如我们        又想支持
//300元定金购买,那我们就在改链中增加一个节点即可:
var order300 = function () {
// todo
};
chainOrder300 = new Chain(chainOrder300)
chainOrder500.setNextSuccessor(chainOrder300)
chainOrder300.setNextSuccessor(chainOrder200)

代码实现:

小结

只要运用得当职责链模式可以很好的帮助我们管理代码。

假设有一个售卖手机的电商网站,经过分别缴纳500元定金和200元定价的两轮预定后(订单此时生成),现在已经到了正式购买的阶段。公司针对支付过定金的客户有一定的优惠政策。在正式购买时,已支付过500元定金的客户将获得100元商城优惠券,已支付过200元的客户将获得50元商城优惠券;而之前没有支付过定金的客户将没有任何优惠券,并且在库存有限的情况下,还不一定能买得到;

参数定义:

1.orderType:表示订单类型(定金用户或普通用户),code的值为1的时候是500元定金用户,为2的时候是200元定金用户,为3的时候是普通用户;

2.pay:表示用户是否已经支付定金,值为true或false。虽然用户下过500元的定金的订单,但如果他一直没有支付定金,现在只能以普通用户的身份进行购买;

3.stock:表示普通用户用于购买手机的库存数量,已经支付过500元定金或者200元定金的客户不受此限制;

实现:

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 ){ // 200 元定金购买模式 if ( pay === true ){ 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 优惠券

上面的代码当然能实现需求功能,但是上述代码明显结构不清晰且order函数方法庞大,耦合程度很高;

职责链模式实现:

本文由10bet发布于Web前端,转载请注明出处:三分钟教会你JS设计模式之职责链模式

关键词:

最火资讯