1. 职责链模式
1.1 定义:
职责链模式(Chain of responsibility):是使多个对象都有机会处理请求, 从而避免请求的发送者和接受者之间的耦合关系.将这些对象练成一条链, 并言者这条链传递请求, 直到有一个对象处理它为止.
JavaScript中的作用域链,原型链都是基于职责链模式,都是沿着链一直直到找到为止,职责链就是要搭建这样一个结构,一层一层的传递请求直到处理了为止.
1.2 作用
- 较低耦合度, 它将请求的发送者和接受者解耦.
- 简化了对象. 增强了给对象指派职责的灵活性.允许动态的新增或者删除职责
- 增加新的请求处理类会很方便.
1.3 应用场景
情景: 要提交一个申购申请, 小于100000, 部门负责人处理, 大于100000小于50000, 院负责人处理;大于50000小于1000000群负责人处理, 大于100000, 董事长处理.
我们按照平常的写法
function request(value){
if(value <= 10000){
console.log('移交部门负责人处理');
// code...
}else if(value <= 50000){
console.log('移交院负责人处理')
// code...
}else if(value <= 100000){
console.log('移交群负责人处理')
// code...
}else if(value > 100000){
console.log('移交董事长处理')
// code...
}
}
request(20000) // 移交院负责人处理
上面的代码需求虽然可以解决, 但是if...else的代码结构有点麻烦,不是很优雅,如果需要修改每个分支或者新添加的时候, 必须修改整个request函数,违反了开闭原则, 我们可以使用职责链模式来改写一下代码.
//将每个分支结构分离:
function director01(value){
if( value <= 10000 ){
console.log("移交部门负责人处理。");
// code……
}else{
//移交给下一个处理人
director02(value);
}
}
function director02(value){
if( value <= 50000 ){
console.log("移交院负责人处理。");
// code……
}else{
//移交给下一个处理人
director03(value);
}
}
function director03(value){
if( value <= 100000 ){
console.log("移交群负责人处理。");
// code……
}else{
//移交给下一个处理人
director04(value);
}
}
function director04(value){
if( value > 100000 ){
console.log("移交董事长处理。");
// code……
}
}
//只需要从第一个处理人开始
director01(20000);
现在我们通过职责链模式将结构的每个分支分开, 耦合度比上面的写法要好很多.但是每个处理层必须强关联下一个处理层,不然就没办法链式调用, 这又是一个很严重的问题, 层层之间的耦合还是很高, 假设要添加下一个处理层. 那么要改的地方就有上下两处. 非常麻烦, 我们可以将代码继续修改并优化一下
//只需要从第一个处理人开始
class Chain{
constructor(){
// 当前职责链的长度
this.length = 0;
// 保存当前职责链
this.successor = [];
}
setSuccessor(...rest){
this.length = rest.length;
this.successor = rest
}
request(...rest){
// 第一种写法
// 利用自执行函数传递index绑定函数上下文 index->指向当前职责链的位置
(function dispose(index){
// 判断index 是否在职责链的范围内
if(index > this.length) {
return '无法处理'
}
// 通过index 获取对应的职责对象
let result = this.successor[index](...rest);
// 如果返回了next 就递归调用dispose 否者返回 result
if(result === 'next'){
index++;
dispose.call(this,index)
}else{
return result
}
}).call(this,0);
/*
上面的利用函数递归 稍微有点麻烦,可以用如下的代码稍微简化一点
*/
// 第二种写法
// 利用while循环遍历, 当result不为next是停止循环
let index = 0,
result = this.successor[index](...rest);
while(result === 'next'){
result = this.successor[++index](...rest);
}
return result
}
}
//将每个分支结构分离:
function director01(value) {
if (value <= 10000) {
console.log("移交部门负责人处理。");
//some code……
} else {
//无须再强关联下一个处理函数
return "next";
}
}
function director02(value) {
if (value <= 50000) {
console.log("移交院负责人处理。");
//some code……
} else {
//无须再强关联下一个处理函数
return "next";
}
}
function director03(value) {
if (value <= 100000) {
console.log("移交群负责人处理。");
//some code……
} else {
//无须再强关联下一个处理函数
return "next";
}
}
function director04(value) {
if (value > 120000) {
console.log("移交董事长处理。");
//some code……
return true
}
}
//实现链
let request = new Chain();
//设置处理队列
request.setSuccessor(
director01,
director02,
director03,
director04,
);
//调用
let res = request.request(120003);// 移交董事长处理
总结: 当有多个对象处理同一个请求时, 具体哪个对象处理该请求由运行时刻自动确定, 在不明确接受者的情况下, 使用 职责链模式非常合适, 职责链模式使得客户端只需要将请求发送到职责链上即可, 无需关心请求的处理细节和请求的传递, 职责链模式在内部将请求的方法者和请求的处理解耦了.
网友评论