定义:定义了一系列的算法,并将每个算法封装起来,使它们可以互相替换
三种角色
- 策略(Strategy):实现不同算法的接口
- 具体策略(Concrete Strategy):实现策略定义的接口,提供具体的算法实现
- 上下文(Context):持有一个策略对象的引用,用一个ConcreteStrategy 对象来配置,维护一个对 Strategy 对象的引用
类比:就像你去商店买东西,你可以选择用现金支付、刷信用卡或使用移动支付。这些支付方式就是不同的策略
应用场景
- 在运行时选择算法的不同变体
- 有许多相关类,仅行为有差异
优缺点
- 优点
- 避免使用多重条件判断语句
- 符合开闭原则,可以在不修改客户端代码的情况下引入新的策略
- 缺点
- 客户端必须知道所有策略类,并自行决定使用哪一个
- 可能会造成很多策略类
实现代码(表单验证功能)
interface Strategy {
[key: string]: (value: string, ...args: any[]) => string | void;
}
interface Rule {
strategy: string;
errorMsg: string;
}
let strategies: Strategy = {
isNonEmpty: (value: string, errorMsg: string) => {
if (value === '') {
return errorMsg;
}
},
minLength: (value: string, length: number, errorMsg: string) => {
if (value.length < length) {
return errorMsg;
}
},
// 可以添加其他验证策略...
};
class Validator {
cache: Array<() => string | void> = []; // 保存校验规则
add(value: string, rules: Rule[]) {
for (let rule of rules) {
let strategyAry = rule.strategy.split(':');
let errorMsg = rule.errorMsg;
this.cache.push(() => {
let strategy = strategyAry.shift() as string; // 用户挑选的strategy
strategyAry.unshift(value); // 把input的value添加进参数列表
strategyAry.push(errorMsg); // 把errorMsg添加进参数列表
return strategies[strategy].apply(null, strategyAry);
});
}
}
start() {
for (let validatorFunc of this.cache) {
let errorMsg = validatorFunc();
if (errorMsg) { // 如果有确切的返回值,说明校验没有通过
return errorMsg;
}
}
}
}