基本概念
策略模式 (Strategy Pattern)又称政策模式,其定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。封装的策略算法一般是独立的,策略模式根据输入来调整采用哪个算法。关键是策略的实现和使用分离。
现实生活中的例子
多功能螺丝刀:
我家就有一套多功能螺丝刀,一个盒子,里面有一个螺丝刀把手主体,以及大大小小各种形状的刀头,一共几十种。买这一套螺丝刀的目的也是当年为了拆卸电脑,电脑里面大大小小各种螺丝,一把普通的螺丝刀可搞不定啊。多功能螺丝刀规格多,基本能覆盖所有拆机需要的螺丝刀的类型。更换螺丝刀刀头就相当于是更换策略。
双十一:
电商们双十一的各种促销政策也是一种策略的选择,什么满100减30,满200减50,7.8折,抵用券、代金券等等,一系列都是策略模式的现实体现。
策略模式例子还有很多,换轮胎、出行方式选择、春节回婆家还是回娘家等都是策略模式。
应用场景
- 多个算法只在行为上稍有不同的场景,这时可以使用策略模式来动态选择算法;
- 算法需要自由切换的场景;
- 有时需要多重条件判断,那么可以使用策略模式来规避多重条件判断的情况;
优缺点
优点:
- 策略之间相互独立,但策略可以自由切换,这个策略模式的特点给策略模式带来很多灵活性,也提高了策略的复用率;
- 如果不采用策略模式,那么在选策略时一般会采用多重的条件判断,采用策略模式可以避免多重条件判断,增加可维护性;
- 可扩展性好,策略可以很方便的进行扩展;
缺点:
- 策略相互独立,因此一些复杂的算法逻辑无法共享,造成一些资源浪费;
- 如果用户想采用什么策略,必须了解策略的实现,因此所有策略都需向外暴露,这是违背迪米特法则/最少知识原则的,也增加了用户对策略对象的使用成本。
实现
实现策略模式需要清楚以下几个概念:
-
Context,封装上下文,根据需要调用需要的策略,屏蔽外界对策略的直接调用,只对外提供一个接口,根据需要调用对应的策略;
-
Strategy :策略,含有具体的算法,其方法的外观相同,因此可以互相代替;
-
StrategyMap :所有策略的合集,供封装上下文调用;
const StrategyMap = {}
function context(type, ...rest) {
return StrategyMap[type] && StrategyMap[type](...rest)
}
StrategyMap.minus100_30 = function (price) {
return price - Math.floor(price / 100) * 30
}
context('minus100_30', 270)