如果可以,请先查看《重构多重嵌套的代码 - 思考》,对于您接下来的阅读会有些帮助。
本文链接:http://www.cnblogs.com/zhenghongxin/p/8687587.html
职责链模式
职责链模式(称责任链模式)将请求的处理对象像一条长链一般组合起来,形成一条对象链。请求并不知道具体执行请求的对象是哪一个,这样就实现了请求与处理对象之间的解耦。
简单的来说,如果你的拥有执行该业务的权限,那么你执行。如果没有此权限,那递交给你的上级。如果上级拥有权限处理该事务,那么上级执行。如果上级没有执行权限,那提交给上级的上级,直到最高权限为止。这条链路上,只要其中一个执行了,那么下面就不用再继续执行下去了。
场景
在节约流量的情况下,我们弹窗的优先级为:文字弹窗 > 图片弹窗 > 视频弹窗 ,可以抽象为:如果文字弹窗允许,那么就执行文字弹窗即可。如果文字弹窗不行,找上级图片弹窗,以此类推,我们容易写出来的代码可能是(依旧是各种嵌套执行,可以查看我的上篇博客):
var h5 = {
init: function() {
// 弹出优先级 : 文字 - 图片 - 视频
h5.popupText();
},
/*
* 文字弹窗
*/
popupText: function() {
api.getText().done(function(re) {
if (re.code == 1) {
// 显示文字弹窗 ...
}
}).always(function(re = {}) {
if (re.code != 1) {
h5.popupImg(); // 继续图片弹窗
}
});
},
/*
* 图片弹窗
*/
popupImg: function() {
api.getImg().done(function(re) {
if (re.code == 1) {
// 显示图片弹窗 ...
}
}).always(function(re = {}) {
if (re.code != 1) {
h5.popupVideo(); // 继续视频弹窗
}
});
},
/*
* 视频弹窗
*/
popupVideo: function() {
// 显示视频弹窗 ...
}
}
可以看到,在每个方法中,用if嵌套去判断。或者是更为恐怖的一层多重判断全部挤在一起:
var h5 = {
init: function() {
// 弹出优先级 : 文字 - 图片 - 视频
api.getText().done(function(re) {
if (re.code == 1) {
// 显示文字弹窗 ...
}
return;
}).always(function(re = {}) {
api.getImg().done(function(re) {
if (re.code == 1) {
// 显示图片弹窗 ...
}
return;
}).always(function(re = {}) {
if (re.code != 1) {
h5.popupVideo(); // 继续视频弹窗
}
});
});
},
}
这样子做的问题在于:
多重嵌套,没有很直观的一个业务体现,新人进来很容易改错,最大的问题在于,如果要改变一下弹窗顺序呢?几乎完全得重新改写,重新测试。某些人会说改写没问题,但新手就是很容易犯这样子的改写错误,而且代码量现在很少。
重写:
var h5 = {
init: function() {
// 弹窗职能链调用
var chain = new MiniChain();
chain.next(h5.popupText).next(h5.popupImg).next(h5.popupVideo).go();
},
/*
* 文字弹窗
*/
popupText: function() {
var isShow = false;
api.getText().done(function(re) {
if (re.code == 1) {
// 显示文字弹窗 ...
isShow = true;
} else {
// 其他场景处理 ...
}
return re;
});
return isShow;
}
},
/*
* 图片弹窗
*/
popupImg: function() {
var isShow = false;
api.getImg().done(function(re) {
if (re.
switch == 1) {
isShow = true;
// 图片弹窗显示
}
});
return isShow;
},
/*
* 视频弹窗
*/
popupVideo: function() {
// 显示视频弹窗 ...
}
}
职能链的按优先级的配置和调度,最大的重点是:如果我们改变弹窗顺序呢?如何改变?
针对这段代码:
chain.next(h5.popupText).next(h5.popupImg).next(h5.popupVideo).go();
做一下改变即可:
chain.next(h5.popupText).next(h5.popupImg).next(h5.popupVideo).go();