策略模式

112 阅读3分钟

基本概念

策略模式 (Strategy Pattern)又称政策模式,其定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。封装的策略算法一般是独立的,策略模式根据输入来调整采用哪个算法。关键是策略的实现和使用分离

现实生活中的例子

多功能螺丝刀:

我家就有一套多功能螺丝刀,一个盒子,里面有一个螺丝刀把手主体,以及大大小小各种形状的刀头,一共几十种。买这一套螺丝刀的目的也是当年为了拆卸电脑,电脑里面大大小小各种螺丝,一把普通的螺丝刀可搞不定啊。多功能螺丝刀规格多,基本能覆盖所有拆机需要的螺丝刀的类型。更换螺丝刀刀头就相当于是更换策略。

双十一:

电商们双十一的各种促销政策也是一种策略的选择,什么满100减30,满200减50,7.8折,抵用券、代金券等等,一系列都是策略模式的现实体现。

策略模式例子还有很多,换轮胎、出行方式选择、春节回婆家还是回娘家等都是策略模式。

应用场景

  1. 多个算法只在行为上稍有不同的场景,这时可以使用策略模式来动态选择算法;
  2. 算法需要自由切换的场景;
  3. 有时需要多重条件判断,那么可以使用策略模式来规避多重条件判断的情况;

优缺点

优点:

  1. 策略之间相互独立,但策略可以自由切换,这个策略模式的特点给策略模式带来很多灵活性,也提高了策略的复用率;
  2. 如果不采用策略模式,那么在选策略时一般会采用多重的条件判断,采用策略模式可以避免多重条件判断,增加可维护性;
  3. 可扩展性好,策略可以很方便的进行扩展;

缺点:

  1. 策略相互独立,因此一些复杂的算法逻辑无法共享,造成一些资源浪费;
  2. 如果用户想采用什么策略,必须了解策略的实现,因此所有策略都需向外暴露,这是违背迪米特法则/最少知识原则的,也增加了用户对策略对象的使用成本。

实现

实现策略模式需要清楚以下几个概念:

  1. Context,封装上下文,根据需要调用需要的策略,屏蔽外界对策略的直接调用,只对外提供一个接口,根据需要调用对应的策略;

  2. Strategy :策略,含有具体的算法,其方法的外观相同,因此可以互相代替;

  3. 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)