策略模式
策略模式与简单工厂类似,针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
引例
商场收银软件,根据商品单价和商品数量收费。然而,报价管理模块往往包含不同级别的客户,给予不同级别的折扣,例如:
- 普通客户:原价
- 老客户:根据年限,给予折扣
- 大客户:根据累计消费,给予折扣
- 客户购买量:对于新老客户都适用
- 报价人员职位高低
- “满300返100”
- CashNormal:正常收费
- CashRebate:打折收费
- CashReturn:返利收费
- 现金收取工厂:根据条件返回相应的对象
折扣数量和满减数量会更改,也可能会添加新的功能,每次更改都需要改写代码(根据上图代码理解),重新编译部署。
策略模式
- 使用策略模式可以将行为和环境分开,环境类负责维持和查询行为类,各种算法则在具体策略类中提供。
- 由于算法和环境独立,算法的增减、删改不会影响环境和客户端。出现新的需求,只需实现新的策略类,并在客户端登记。相当于“可插入式”的算法。
策略模式:对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。 - 环境角色(Context):持有一个Strategy类的引用(上下文对象),负责和具体的策略交互。
- 抽象策略类(Strategy):一个抽象角色,通常由一个接口和抽象类实现。该角色给出所有具体的策略类所需的结构。
- 具体策略角色(ConcreteStrategy):包装了相关的算法或行为。
策略模式功能:把具体算法从具体业务处理中独立。当出现多个if-else时考虑使用策略模式。在策略模式中,由客户端、上下文选择具体的策略算法。
策略模式的使用场景
- 出现同一个算法,有很多不同的实现的情况,可以使用策略模式来把这些“不同的实现”实现成为一个算法的类层次
- 出现抽象一个定义了很多行为的类,并且是通过多个if-else语句来选择这些行为的情况,可以使用策略模式来代替这些条件语句
优缺点
优点
- 策略模式可以避免让客户端涉及不必要接触的复杂的之和算法相关的数据
- 避免使用难以维护的多重条件选择语句
- 更好的扩展
缺点
- 上述策略模式,把分支判断又放回到客户端,要改变需求算法时,还是要去更改客户端的程序。
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
- 增加了对象的数目
- 只适合扁平的算法结构
策略模式的本质
分离算法、选择实现
策略与工厂结合
把客户端的分支判断放到环境角色里面。
- 简单工厂模式的用法:
CashSuper csuper = CashFactory.createCashAccept(cbxType.SelectedItem.ToString());
... = csuper.acceptCash(...)
- 策略模式和简单工厂结合的用法
CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
…=csuper.GetResult(…)
简单工厂模式需要让客户端认识两个类,改进的策略模式只需让客户端认识一个类。耦合更低
【文章所有内容皆整理自王鲁老师《设计模式》课件】