背景
抽象:需要不同场景执行不同的逻辑时。
具象:比如运算符,需要加数时,使用相加逻辑,乘法类似。
分析
if、switch都可以实现这个目的,比如
const executor = (type: string, ops1: number, ops2: number) => {
if (type === "add") {
return ops1 + ops2;
} else if (type === "mul") {
return ops1 * ops2;
} else {
throw err;
}
};
问题:如果我要拓展除法,那我得在 executor 里继续补充判断逻辑、执行逻辑,这个 executor 明显是很多人会编辑的模块,当逻辑都杂糅在此处时,代码就会耦合,明显不符合开闭原则
解决方案
我们将执行逻辑先剥离出来
const add = (ops1: number, ops2: number) => {
return ops1 + ops2;
};
const mul = (ops1: number, ops2: number) => {
return ops1 * ops2;
};
const executor = (type: string, ops1: number, ops2: number) => {
if (type === "add") {
return add(ops1, ops2);
} else if (type === "mul") {
return mul(ops1, ops2);
} else {
throw err;
}
};
这样,我们在重构或实现新的执行逻辑时,就和executor无关了
接下来,我们将判断逻辑也剥离,在需要用不同执行逻辑的地方,使用不同的执行逻辑,
我们定义一个执行者,给它传入什么执行逻辑,它就执行什么
class Executor {
run: () => void;
contructor() {}
setRun(run) {
this.run = run;
}
execute(...arguments) {
this.run(...arguments);
}
}
const calculator = new Executor();
// 我们可以这样使用
calculator.setRun(add);
let rsl = calculator.exec(1, 2);
// 也可以这么使用
if (type === "mul") {
calculator.setRun(mul);
rsl = calculator.exec(1, 2);
}
if (type === "add") {
calculator.setRun(add);
rsl = calculator.exec(1, 2);
}
这给我们了很多好处
- 很大的灵活性,而不是所有的判断逻辑全得写在 executor 函数中
- 提供了 Executor 这个类的范式,在多人开发中有一个规范
但是,我们并不清楚执行逻辑是什么类型的逻辑,这很被动,我们需要定义这个类型,重新拿回主动权
对于我们上面定义的 calculator,我们能知道它上用来执行两数处理的,所以我们可以定义 执行逻辑 的类型
class Run {
run: (ops1: number, ops2: number) => number;
}
所有的执行逻辑的定义都得继承自Run类
class Add extends Run {
run(ops1: number, ops2: number) {
return ops1 + ops2;
}
}
class Mul extends Run {
run(ops1: number, ops2: number) {
return ops1 * ops2;
}
}
这样我们以后写新的执行逻辑时,就有一个规范了。
比如设计一个减法的逻辑,我们只需要
class Sub extends Run {
run(ops1: number, ops2: number) {
return ops1 - ops2;
}
}
const calculator = new Executor();
calculator.setRun(new Sub());
calculator.execute(1, 2);
好啦,这就是一个策略模式的原型啦,我们将执行逻辑 = Strategy来表达,而Executor = Context来表达。
如下
class Strategy {
execute: (ops1: number, ops2: number) => number;
}
class Context {
strategy: Strategy;
constructor(strategy: Strategy) {
this.strategy = strategy;
}
setStrategy(strategy: Strategy) {
this.strategy = strategy;
}
execute(ops1: number, ops2: number) {
return this.strategy.execute(ops1, ops2);
}
}
const calculator = new Context(new Add());
calculator.execute(1, 2);
calculator.setStrategy(new Mul());
calculator.execute(1, 2);
calculator.setStrategy(new Sub());
calculator.execute(1, 2);
这就是一个完整的策略模式啦~~~
结尾
各位看官,给个赞赞吧~~~~