大话设计模式 | 2. 策略模式
《 大话设计模式 》是作者「程杰」通过趣味的场景设置,以诙谐的表达来解读和剖析「面向对象」编程思维和「设计模式」。书中的示例代码是以 .NET 的 C# 语言编写而成。
本文是我对《大话设计模式》的学习系列笔记的第二篇,策略模式。
1. 定义
策略模式 (Strategy Pattern),定义了算法家族,分别封装起来(封装变化点),让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
策略模式减少了各种算法类与使用算法类之间的耦合,使得:
算法可独立于使用该算法的客户端而进行变化
客户端可以根据外部条件选择不同的策略来解决不同的问题(算法由客户端选择)
2. 组成
与简单工厂模式,策略模式主要是由三个角色组成:
「抽象策略(Strategy)」角色,是「具体策略」的父类,定义所有支持的算法的公共接口。
「具体策略(ConcreteStrategy)」角色,封装了具体的算法或行为。
「环境(Context)」角色,用一个具体策略来配置,维护一个对抽象策略对象的引用。
3. 使用步骤
主要包含四步:
创建「抽象策略」类,并定义所有支持的算法的公共接口;
创建「具体策略」类,并定义具体的算法实现;
创建「环境」类,通过构造方法,传入具体的策略参数,并根据具体的策略对象来调用其算法;
外界通过调用「环境」类的方法,通过传入不同参数来实例化不同的策略,从而得到不同的结果。
4. 实例
《大话设计模式》中,是通过一个商场的收银系统为例进行说明的。商场收银系统需要能够处理正常收费、商品打折和节假日满减等各种活动。
这里正常收费、打折和满减是该系统需要实现的具体算法,他们都共用的一个收费的接口。
创建抽象策略类
创建 CashSuper
的抽象策略类,并定义所支持的算法的公共接口 acceptCash()
。
创建具体策略类
创建具体策略类(CashNormal
、CashRebate
、CashReturn
等),来继承 CashSuper
的抽象策略类,并实现 acceptCash()
方法,来定义具体的算法。
创建环境类
通过构造方法,传入具体的收费策略,并根据具体的策略对象来调用其算法,得到不同的计算结果。
调用环境类的方法
在主函数中(客户端),通过传入相应的策略对象,并调用环境类的 GetResult()
方法,来得到收费的结果,让具体的算法与客户端进行了隔离。
但是,这里存在一个很大的问题,虽然具体的算法与客户端进行了隔离,但是还是要在客户端去判断需用用哪一个算法。
与简单工厂模式结合
在简单工厂模式中,我们是通过创建工厂类,并定义静态方法,通过传入不同参数来创建不同具体产品类的实例。
那么,我们也可以将实例化的具体策略过程,通过简单工厂的应用,从客户端转移到环境类中。
相应的,客户端代码就比较简单了,只需调用环境类,传入收费类型即可。
在客户端的代码中,对比简单工厂模式,只需认识一个 CashContext
类就可以了。而如果通过简单工厂模式的话,客户端需要认识 CashSuper
和 CashFactory
两个类。这使得具体的收费算法彻底与客户端分离了。
5. 参考
本文参考了这两篇文章:
具体代码可参考:https://github.com/puran1218/DesignPatternWithCSharp
版权声明: 本文为 InfoQ 作者【Puran】的原创文章。
原文链接:【http://xie.infoq.cn/article/05513a9ca11f3850759bf275e】。文章转载请联系作者。
评论