职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
优点:
- 请求发送者只需要知道链中的第一个节点,从而弱化了发送者和一组请求者之间的强联系。
- 使用职责链模式之后,链中的节点对象,可以灵活的拆分重组。增加或删除一个节点,或者改变节点在链中的位置都是轻而易举可以实现的。
- 可以手动指定起始节点,请求并不是非得从链中的第一个节点开始传递。
缺点:
- 不能保证请求一定会被链中的节点处理,可能得不到答案,无响应或者抛出异常。
- 可能很多节点没有实质作用,从性能方面考虑,回到了性能损耗。
举栗子:公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过 500 元定金的用
户会收到 100 元的商城优惠券,200 元定金的用户可以收到 50 元的优惠券,而之前没有支付定金
的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。
// 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;
};
现在我们把 3 个订单函数分别包装成职责链的节点:
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 优惠券
chainOrder500.passRequest( 3, true, 500 ); // 输出:普通购买,无优惠券
chainOrder500.passRequest( 1, false, 0 ); // 输出:手机库存不足