priceCalculate 函数的实现,这是违反开放-封闭原则的;可复用性差,如果在其他的地方也有类似这样的算法,但规则不一样,上述代码不能复用;
我们可以改造一下,将计算折扣的 算法部分提取出来 保存为一个对象,折扣的 类型作为 key ,这样索引的时候 通过对象的键值索引调用具体的算法 :
这样 算法的实现和算法的使用就被分开了 ,想添加新的算法也变得十分简单:
如果你希望计算算法隐藏起来,那么可以借助 IIFE 使用闭包的方式,这时需要添加增加策略的入口,以方便扩展:
这样算法就被隐藏起来,并且预留了增加策略的入口,便于扩展。
3. 策略模式的通用实现
根据上面的例子提炼一下策略模式,折扣计算方式可以被认为是策略(Strategy),这些策略之间可以相互替代,而具体折扣的计算过程可以被认为是封装上下文(Context),封装上下文可以根据需要选择不同的策略。
主要有下面几个概念:
Context:封装上下文,根据需要调用需要的策略,屏蔽外界对策略的直接调用,只对外提供一个接口,根据需要调用对应的策略;
Strategy:策略,含有具体的算法,其方法的外观相同,因此可以互相代替;
StrategyMap:所有策略的合集,供封装上下文调用;
结构图如下:

下面使用通用化的方法实现一下。
通用实现看起来似乎比较简单,这里分享一下项目实战。
4. 实战中的策略模式
4.1 表格 formatter
这里举一个 Vue + ElementUI 项目中用到的例子,其他框架的项目原理也类似,和大家分享一下。
Element 的表格控件的 Column 接受一个
formatter 参数,用来格式化内容,其类型为函数,并且还可以接受几个特定参数,像这样:
Function(row,column,cellValue,index) 。以文件大小转化为例,后端经常会直接传 bit 单位的文件大小,那么前端需要根据后端的数据,根据需求转化为自己需要的单位的文件大小,比如 KB/MB。
首先实现文件计算的算法:
那么在组件中我们可以直接:
代码实例可以参看 codepen – 策略模式实战
运行结果如下图:

4.2 表单验证
除了表格中的 formatter 之外,策略模式也经常用在表单验证的场景,这里举一个 Vue + ElementUI 项目的例子,其他框架同理。










