这是我参与更文挑战的第4天,活动详情查看: 更文挑战javascript
职责链模式就是当一个对象 a
,有多种可能的请求对象 b
、c
、d
、e
时,咱们为 b
、c
、d
、e
分别定义一个职责,组成一条职责链,这样 a
只须要找到 b
发起请求,而后沿着职责链继续请求,直到找到一个对象来处理 a
。java
女孩子们都喜欢结伴吃饭,我如今要找一我的一块儿吃饭,代码以下:git
嗯.....女程序员确实是这样,吃个饭也要写代码发请求的。程序员
const [ astrid, brooke, calliope ] = [{
name: 'astrid',
requirement: '我要吃湘菜'
},{
name: 'brooke',
requirement: '我要找10我的一块儿吃饭'
},{
name: 'calliope',
requirement: '我要和男友一块儿吃饭'
}]
// 是否知足Astrid的要求
function isSatisfyAstrid (user) {
// ... 省略...
}
// 是否知足Brooke的要求
function isSatisfyBrooke (user) {
// ... 省略...
}
// 是否知足Calliope的要求
function isSatisfyCalliope (user) {
// ... 省略...
}
function eatDinner () {
if (isSatisfyAstrid()) {
console.log(`我能够和 astrid 一块儿吃晚饭啦`)
} else if (isSatisfyBrooke()) {
console.log(`我能够和 brooke 一块儿吃晚饭啦`)
} else if (isSatisfyCalliope()) {
console.log(`我能够和 calliope 一块儿吃晚饭啦`)
} else {
console.log(`哎呀,我要一我的吃晚饭啦`)
}
}
复制代码
因为 astrid
、brooke
、calliope
吃晚饭的要求不一样,我须要一个个去发起晚餐请求,直到找到答应和我一块儿吃晚饭的人。github
在这里,我假设 astrid
的要求是要吃湘菜,brooke
的要求是要找 10 我的凑一桌一块儿吃,calliope
的要求是只想和男友一块儿吃饭。web
上述代码用 if-else
的作法很是死板,假如我又多了个朋友 davi
,我必须再次修改 eatDinner
方法,违反了开放-封闭原则,不易于维护。设计模式
下面使用职责链来优化上述代码,代码以下:markdown
// 给每一个人定义一个职责
const chainOrderA = new Chain(isSatisfyAstrid)
const chainOrderB = new Chain(isSatisfyBrooke)
const chainOrderC = new Chain(isSatisfyCalliope)
// 设置一下职责链的顺序
chainOrderA.setNextSuccessor(chainOrderB)
chainOrderB.setNextSuccessor(chainOrderC)
// 发起请求,这时我只须要向职责链上的第一我的请求
function eatDinner () {
chainOrder.passRequest() // 发起请求
}
复制代码
将职责做为转入 Chain
函数,并经过 setNextSuccessor
定义该职责的下一个职责函数,组成一条 chainOrderA
-> chainOrderB
-> chainOrderC
职责链,这时,我只须要向 astrid
发起请求,若是请求失败,将会沿着职责链继续请求,直到找到和我一块儿吃晚饭的人。app
下面将讲述在实际场景中怎么使用职责链模式,怎么实现 Chain
方法,请继续往下看。函数
下周就是 618,电商网站免不得会推出商品预售活动,假设在 618 以前,预付 500 定金,可得到 100 元优惠券,预付 200 元定金,可得到 50 优惠券,未付定金则无优惠券。618 当天的购买事件以下:
先上代码。
本文代码仅举例说明,和业务无关。
const order = function (orderType) {
if (orderType === 500) {
console.log('已预付500定金,享有100优惠券')
} else if (orderType === 200) {
console.log('已预付200定金,享有50元优惠券')
} else {
console.log('未付定金,无优惠')
}
}
order(500) // '已预付500定金,享有100优惠券'
复制代码
熟悉的代码,一长段的 if-else
判断,不利于维护。
定义一个职责类 Chain
。
fn
做为参数;setNextSuccessor
指定该职责的下一个职责函数;passRequest
发起对职责函数 fn
的请求;
nextSuccesstor
,说明请求失败,继续请求职责链上的下一个职责函数;nextSuccesstor
,说明找到了接收请求的对象,返回请求结果,再也不继续执行职责链上的下一个职责函数。代码以下:
const Chain = function(fn) {
this.fn = fn;
this.successor = null;
};
Chain.prototype.setNextSuccessor = function(successor) {
return this.successor = successor;
}
Chain.prototype.passRequest = function() {
const ret = this.fn.apply(this, arguments)
if (ret === 'nextSuccessor') {
return this.successor && this.successor.passRequest.apply(this.successor, arguments);
}
return ret;
};
复制代码
而后定义职责类实例,经过 setNextSuccessor
组成职责链,代码以下:
const order500 = function (orderType) {
if (orderType === 500) {
console.log('已预付500定金,享有100优惠券')
} else {
return 'nextSuccessor'
}
}
const order200 = function (orderType) {
if (orderType === 200) {
console.log('已预付200定金,享有50元优惠券')
} else {
return 'nextSuccessor'
}
}
const chainOrder500 = new Chain(order500)
const chainOrder200 = new Chain(order200)
chainOrder500.setNextSuccessor(chainOrder200)
chainOrder500.passRequest(200)
复制代码
上述代码将 chainOrder500
和 chainOrder200
组成一条职责链,无论用户是哪一种类型,都只须要向 chainOrder500
发起请求,若是 chainOrder500
没法处理请求,就会继续沿着职责链发起请求,直到找到能处理请求的职责方法。
经过职责链模式,解耦了请求发送者和多个接收者之间的复杂关系,再也不须要知道具体哪一个接收者来接收发送的请求,只须要向职责链的第一个阶段发起请求。
职责链模式,帮助咱们管理代码,下降发起请求和接收请求对象之间的耦合。
职责链模式中的节点数量和顺序是能够自由变更的,能够在运行时决定链中包含哪些节点。
可经过 github源码 进行实操练习。
但愿能对你有所帮助,感谢阅读~别忘了点个赞鼓励一下我哦,笔芯❤️
· 往期精彩 ·