js里的职责链模式
职责链模式
职责链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
该模式类似于调用原型方法一样:在该对象没有该方法时向上一个原型上寻找方法;该模式这是该方法无法处理这个请求时,用下一个方法处理该请求,这样形成一个链,每个方法都有可能被调用。
这里用一个表单验证做例子:
btn.addEventListener("click", function (event) {
if (input.value.length == 0) {
console.log("这里要输入东西");
} else {
if (Number.isNaN(+input.value)) {
console.log("这里是数字");
if (input.value.length < 3) {
console.log("这里要三个以上数字");
}
}
}
});
可以看到代码可读性很差,如果用职责链模式来重构:
function checkEmpty() {
if (input.value.length == 0) {
console.log("这里要输入东西");
}
return "next";
}
function checkNumber() {
if (Number.isNaN(+input.value)) {
console.log("这里是数字");
}
return "next";
}
function checkLength() {
if (input.value.length < 3) {
console.log("这里要三个以上数字");
}
return "next";
}
class Chain {
constructor(fn) {
this.checkRule = fn;
this.nextRule = null;
}
addRule(nextRule) {
this.nextRule = nextRule;
}
check() {
this.checkRule() == "next" ? this.nextRule.check() : null;
}
}
const isEmpty = new Chain(checkEmpty);
const isNumber = new Chain(checkNumber);
const isLength = new Chain(checkLength);
const check = new Chain(() => "next");
check.addRule(isEmpty);
isEmpty.addRule(isNumber);
isNumber.addRule(isLength);
isLength.addRule({ check: () => "end" });
btn.addEventListener("click", () => {
check.check();
});
现在代码可读性变强了,但是很明显变得相当庞大,并且每个链上的函数都得返回一个相同的“next”,这里用装饰模式稍微修改一下代码,做成链式调用:
function checkEmpty() {
if (input.value.length == 0) {
console.log("这里要输入东西");
}
}
function checkNumber() {
if (Number.isNaN(+input.value)) {
console.log("这里是数字");
}
}
function checkLength() {
if (input.value.length < 3) {
console.log("这里要三个以上数字");
}
}
class Chain {
constructor(fn) {
this.checkRule = fn ?? (() => "next");
this.nextRule = null;
}
addRule(nextRule) {
this.nextRule = new Chain(() => (nextRule(), "next"));
return this.nextRule;
}
end() {
this.nextRule = { check: () => "end" };
}
check() {
this.checkRule() == "next" ? this.nextRule.check() : null;
}
}
const checks = new Chain();
checks.addRule(checkEmpty).addRule(checkNumber).addRule(checkLength).end();
这样,代码的可读性更好,并且如果要在规则之间添加新规则,也只需要在调用链里新增而已:
function checkSum() {
const result = Array.prototype.reduce.call(
input.value,
(result, now) => {
return (result += +now);
},
0
);
if (result !== 10) {
console.log("和必须为10");
}
}
const checks = new Chain();
checks.addRule(checkEmpty).addRule(checkNumber).addRule(checkSum).addRule(checkLength).end();
热门相关:无量真仙 第一神算:纨绔大小姐 薄先生,情不由己 大神你人设崩了 横行霸道