纯JavaScript版本的设计模式之策略模式。
定义
定义一组策略,将每种策略单独封装起来,根据相应的场景相互切换,从而实现策略的实现和使用分离开来。
是一种行为型设计模式。
实践
使用不同的分段方法将一段范围([min, max])分割成几段(count)。
形式一:函数形式的策略对象
实现:定义策略对象,用函数将每种策略封装起来。
// 分段方法
const ArrayStatistic = {
// 等距分段
equalIntervalBreaks: (count: number, max: number, min: number): number[] => {
const breaks = [min];
const breakSize = (max - min) / count;
for (let i = 1; i < count; i++) {
breaks.push(breaks[i - 1] + breakSize);
}
breaks.push(max);
return breaks;
},
// 对数分段
logarithmBreaks: (count: number, max: number, min: number): number[] => {
const logMax = Math.log(max) / Math.LN10;
const logMin = Math.log(min) / Math.LN10;
const breaks = ArrayStatistic.equalIntervalBreaks(count, logMax, logMin);
return breaks.map((value) => 10 ** value);
},
// 平方根分段
sqrtBreaks: (count: number, max: number, min: number): number[] => {
const sqrtMax = Math.sqrt(max);
const sqrtMin = Math.sqrt(min);
const breaks = ArrayStatistic.equalIntervalBreaks(count, sqrtMax, sqrtMin);
return breaks.map((value) => value * value);
}
};
使用:
const strategy = (type, count, max, min) {
return ArrayStatistic[type](count, max, min);
}
strategy('equalIntervalBreaks', 2, 10, 2);
strategy('logarithmBreaks', 2, 10, 2);
形式二:高阶函数
实现三种策略:
// 等距分段
const equalIntervalBreaks = (count: number, max: number, min: number): number[] => {
const breaks = [min];
const breakSize = (max - min) / count;
for (let i = 1; i < count; i++) {
breaks.push(breaks[i - 1] + breakSize);
}
breaks.push(max);
return breaks;
},
// 对数分段
const logarithmBreaks = (count: number, max: number, min: number): number[] => {
const logMax = Math.log(max) / Math.LN10;
const logMin = Math.log(min) / Math.LN10;
const breaks = ArrayStatistic.equalIntervalBreaks(count, logMax, logMin);
return breaks.map((value) => 10 ** value);
},
// 平方根分段
const sqrtBreaks = (count: number, max: number, min: number): number[] => {
const sqrtMax = Math.sqrt(max);
const sqrtMin = Math.sqrt(min);
const breaks = ArrayStatistic.equalIntervalBreaks(count, sqrtMax, sqrtMin);
return breaks.map((value) => value * value);
}
使用:
// 高阶函数
const strategy = (fn, count, max, min) {
return fn(count, max, min);
}
strategy(equalIntervalBreaks, 2, 10, 2);
strategy(logarithmBreaks, 2, 10, 2);
个人Tip:实践开发中常用的是形式一,策略模式是预设计好的,有新增策略就新增函数, 策略对象新增type;形式二更易于扩展,新增函数,使用的地方传函数就好了, 更适用于明确传哪种策略函数, 如果外层还需要判断什么情况选用哪种策略,形式一更合适,个人见解, 大家可以根据应用场景选择适用的形式。
重构
在实际开发中,如果发现一个函数里:
1、条件判断多;
2、每个条件间互不影响;
就可以开始重构了:
1、各个条件单独封装成函数
2、建立判断条件和具体实现之间的映射关系(策略对象)。
快去试试吧,搜索代码中的else if ,或者 switch case,用策略模式重构函数, 让代码优雅起来。
总结
JavaScript中的策略模式常常是用函数去封装、实现。