爱客仕-前端团队博客园

射鸡模式之责任链引发的家族关系错综复杂?

写在正文前

这是js写设计模式的开篇。

行,无耻的做了标题党。被骗进来的只能说,
少年你的内心还不够强大 [/手动笑哭]

为什么要取这么黄暴的名字?因为我认为要是前人都站在巨人的肩膀上为世界提供了这么多代码,那我连巨人的蕾丝裙边都摸不到,只能在石榴裙下顶礼膜拜。

所以按照👆的逻辑。在下根据自行理解的仿写的都算不上是设计模式,顶多算是‘射鸡模式’

咳咳,不瞎逼逼了,那么。。。

正片开始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(function () {
if (爸爸的爸爸叫什么 === '爷爷') {
if (爷爷的爸爸叫什么 === '太爷爷') {
if (爸爸的xxx) {
if (爸爸) {
if () {
...........
}
}
} else {
爷爷的爸爸叫太奶奶[大雾];
}
} else {
爸爸的爸爸叫奶奶[大雾];
}
}
})();

不知道小伙伴在业务需求里应该会不会出现那么多的 if 判断

反正在下有时候会遇见这个问题

两三层都还过得去,要是再多一点,虽然写的时候hold的住,但是也防不住产品经理

“喂,那谁,把里面的xxx改一下”,

boom, shakalaka

最好的办法就是每一层都解耦,上一层不用管下一层,只管传递参数

“这不可能!”,在学校捧着《HTML CSS速成手册》,《Javascript30天入门》的我如是喊道。

其实在设计模式射鸡模式里面, 其实是有相对应的策略——责任链

好比把公交卡一个个传递下去,直到递到如果前面就是刷卡机 “滴,学生卡”

不过在这之前我们需要做一丢丢小事情去处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var Chain = function (fn) {
this.fn = fn; // 传入方法
this.successor = null; // 下一个链条的节点
}
Chain.prototype.nextSuccessor = function (successor) {
return this.successor = successor;
}
Chain.prototype.passRequest = function () {
var ret = this.fn.apply(this, arguments);
// 如果返回值为'nextSuccessor'就调用下一个
if (ret === 'nextSuccessor') {
this.successor && this.successor.passRequest.apply(this, arguments);
}
return ret;
}

上面做完了,可以开始认亲大会了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var fater = function (relation) {
if (relation === '爷爷') {
console.log('爷爷');
} else {
return 'nextSuccessor'
}
}
var grandpa = function (relation) {
if (relation === '太爷爷') {
console.log('太爷爷')
} else {
return 'nextSuccessor'
}
}
var grandfater = function (relation) {
if (relation === '太太爷爷') {
console.log('太太爷爷')
} else {
console.log('没有这个人!')
}
}
var chain_fater = new Chain(father)
var chain_grandpa = new Chain(grandpa)
var chain_grandfater = new Chain(grandfater)
chain_father.setNextSuccessor(chain_grandpa)
chain_grandpa.setNextSuccessor(chain_grandfater)
chain_fater.passRequest('太爷爷') // console: 太爷爷
chain_fater.passRequest('奶奶') // console: 没有这个人
// 如果中间不要爷爷了,那就只要...
chain_fater.setNextSuccessor(chain_grandfater)

有个名人曾经说过:

es6 is very convenient for my life, it gives me free
                                            ——Gentleman.Fangbee

es6给了我编码极大便利,有了让我继续码下去的勇气
                                            ——真特么.方便

说的很有道理,在es6的浪潮里,我们如何能做到独善其身?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 箭头函数无法做构造器
const Chain = function (fn) {
this.fn = fn
this.successor = null
}
Chain.prototype.setNextSuccessor = function (successor) {
// 因为箭头函数this的关系,像上面那样使用this获取到的不指向构造器,
// 故最后还是选用function去实现
// 而是最近的一个作用域,相关资料自行谷歌/百度
this.successor = successor
return // 不这样写公司的eslint通不过ORZ
}
Chain.prototype.passRequest = function (...args) {
const ret = this.fn(...args) //再次感谢es6
// 如果返回值为'nextSuccessor'就调用下一个
if (ret === 'nextSuccessor') {
if (this.successor) { // 拆成这样写依旧是eslint背锅
this.successor.passRequest(...args)
}
}
return ret
}

写在末尾

插科打诨的方式逼逼完了一通自己对设计模式的简单理解。其实我们
代码里时常不自觉的情况下就用到设计模式,只是我们自己都不知道
这叫xxx设计模式。

确实是很方便的玩意儿。以后有什么好用的再做推荐。

上面那一坨大家可以自行实现,如果有什么改良或者更好的实现方式
,可以交流出来供大家学习。

荆轲刺秦王