意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
有这样一个情景: 绩效为 S的人年终奖有 4倍工资,绩效为 A的人年终奖有 3倍工资,而绩效为 B的人年终奖是 2倍工资。假设财务部要求我们提供一段代码,来方便他们计算员工的年终奖。
最简单直接的方式当然是if else,看代码:
但是这样不符合开闭原则,耦合性太高了。
用专业的术语:calculateBonus 函数比较庞大,包含了很多 if-else 语句,这些语句需要覆盖所有的逻辑分支。
calculateBonus 函数缺乏弹性,如果增加了一种新的绩效等级 C,或者想把绩效 S 的奖金系数改为 5,那我们必须深入 calculateBonus 函数的内部实现,这是违反开放封闭原则的。算法的复用性差,如果在程序的其他地方需要重用这些计算奖金的算法呢?我们的选择只有复制和粘贴。
接下来我们用策略模式重构: 策略模式指的是定义一系列的算法,把它们一个个封装起来。将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。
共有方法getBonus会根据策略不同(strategy)调用对应的calculate方法
源码:
interface Strategy {
// 策略模式运算法则
doSomething() : void;
}
class ConcreteStrategy1 implements Strategy {
public doSomething() : void {
console.log('使用的策略1');
}
}
class ConcreteStrategy2 implements Strategy {
public doSomething() : void {
console.log('使用的策略2');
}
}
class ContextofStrategy {
private _strategy : Strategy;
constructor(strategy : Strategy) {
this._strategy = strategy;
}
set strategy(strategy : Strategy) {
this._strategy = strategy;
}
//封装后的策略方法
doOperation() : void {
this._strategy.doSomething();
}
}
function main() {
const strategy1 : Strategy = new ConcreteStrategy1();
const strategy2 : Strategy = new ConcreteStrategy2();
const context : ContextofStrategy = new ContextofStrategy(strategy1);
context.doOperation();
context.strategy = strategy2;
context.doOperation();
}
main();
在前端的用处:表单验证,和一些文字提示弹窗