前言
职责链模式在我们的开发中非常常见,然而在不知道的同学那里,可能你之前都是通过if/else的方式来实现的类似逻辑。职责链主要就是指,在执行一个具体的事情时,不确定使用哪种逻辑时,进行链式的判断,直到找到符合条件的函数或者对象,然后处理。分析,发现其实我们很多的代码的背后逻辑就是职责链模式。
图解
现实中的职责链
现实中的例子非常多,比如,我们在挤公交时,如果人特别多,我们之前是将硬币通过人传递的方式,依次向前传递,直到前面的人是司机或者售票员,这就是一个非常明显的职责链的例子。
代码重构
原先的代码主要是通过if,else进行不断的判断,执行不同的逻辑。
案例说明
重构前
const order = (orderType,pay,stock){
if(orderType === 1){
if(pay === true){
console.log('500元定金,返回100优惠券')
} else {
if(stock > 0 ){
consle.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
}
else if(orderType === 2){
if(pay === true){
console.log('200元定金,返回50优惠券')
} else {
if(stock > 0 ){
consle.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
}else{
if(stock > 0 ){
consle.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
}
重构后
我们按照职责链的设计思想,一步到位,分别包含以下的思路:
- 将不同的购买模式封装为函数
- 实现链式函数,可以不断追加函数,可以在不符合时,实现递交
const order500 = function(orderType,pay,stock){
if(orderType === 1 && pay === true){
console.log('500元定金,返回100优惠券')
} else {
return 'nextSuccessor';
}
}
const order200 = function(orderType,pay,stock){
if(orderType === 2 && pay === true){
console.log('200元定金,返回50优惠券')
} else {
return 'nextSuccessor';
}
}
const orderNormal = function(orderType,pay,stock){
if(stock > 0 ){
console.log('普通购买,无优惠券')
} else {
console.log('库存不足')
}
}
const Chain = function(fn){
this.fn = fn;
this.successor = null;
}
Chain.prototype.setNextSuccessor = function(successor){
return this.successor = successor;
}
Chain.prototype.passRequest = function(){
let ret = this.fn.apply(this, arguments);
if(ret === 'nextSuccessor'){
return this.successor && this.successor.passRequest.apply(this.successor, arguments);
}
return ret;
}
let chainOrder500 = new Chain(order500);
let chainOrder200 = new Chain(order200);
let chainOrderNormal = new Chain(orderNormal);
chainOrder500.setNextSuccessor(chainOrder200);
chainOrder200.setNextSuccessor(chainOrderNormal);
chainOrder500.passRequest(1,false,0);
chainOrder500.passRequest(1,true,10);
chainOrder500.passRequest(2,true,11);
chainOrder500.passRequest(2,false,1);
codepen地址:codepen.io/robinson90/…
番外篇:职责驱动设计以及状态模式的实践
文章链接:mp.weixin.qq.com/s/qQEEnf79F…
需求
解决方案
引入职责驱动概念,从知识的能力的角度,去判断哪个对象具有操作的能力。
但这样的坏处是当加入新的状态时,所有实现接口的状态类都需要变更,不符合设计模式的开闭原则。
状态图:
另一种"职责链"
这种不在典型的职责链设计中,是我个人在开发过程中,自己认为的也符合形式上的链式判断,但最终只确定执行一个最终函数,而不是实现链式递交的。
当然了,也可能这完全不属于任何一种设计模式,不过我觉得设计模式的本质还是为了解决固定场景的固定思维模式,至于叫什么名字应该不是重点。
具体代码如下:
let Chain = function(){
let dutyArr = []
this.addDuty = function(duty){
dutyArr.push(duty)
}
this.opt = function(params){
for(let index in dutyArr){
if(dutyArr[index].judge(params)){
return dutyArr[index].opt && dutyArr[index].opt(params);
}
}
return false
}
}
let ageChainDemo = new Chain();
ageChainDemo.addDuty({
judge:function(params){
let {age} = params;
return age > 18;
},
opt:function(params){
let {age} = params;
return '你已经是成年人了'
}
})
ageChainDemo.addDuty({
judge:function(params){
let {age} = params;
return age > 0 && age < 18;
},
opt:function(params){
let {age} = params;
return '你还是未成年'
}
})
let result = ageChainDemo.opt({age:20});
console.log(result);
let result2 =ageChainDemo.opt({age:10});
console.log(result2);
codepen地址:codepen.io/robinson90/…
与策略模式的区别
乍一看,写法上,职责链与策略模式没什么,都是分别维护不同的函数逻辑,其区别主要是使用条件的判断。
策略模式可以准确的决定使用哪种策略,而且可以确定使用这种策略就能返回结果;而职责链模式,则是将使用条件进行抽象,内置到函数中,通过不断的函数内部判断,如果不符合,需要继续判断传递,直到执行到符合条件的函数并执行。
由此,我们可以这样判定,如果我们对条件属于模糊的,更适合使用职责链。这样要好于写if/else内写复杂的布尔运算,或者使用某个计算变量的结果值,或者使用其他函数的返回结果。
更多
原文链接:www.yuque.com/robinson/de…
更多设计模式的学习与了解,可以移步到我的设计模式专辑:www.yuque.com/robinson/de…