职责链模式的定义是: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象形成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
举一个实际的例子:一款新手机发布会后,经过了缴纳过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();
网友评论