程序员小刘最近很恼火,公司新上马了一个电商促销项目,以发放优惠券的形式来达到商品促销的目的。可是项目上线一段时间后活动进行的并不理想,产品经理一顿分析,认为是促销力度不够,需结合多种形式的活动来达到促销的目的,于是接二连三的找到小刘,今天加一个打折促销活动,明天加一个满减促销活动。。。小刘无奈只能加班加点的改动代码,本就稀少的头发又不见了几根。
你作为小刘的资深基友,看着他的一堆if else,眉头微皱,说道,你这样不行啊,鬼知道这产品经理还有什么馊主意,你这种情况建议用策略模式梳理一下,后期扩展也很方便。小刘一听,两只熊猫眼一簇,问道,策略模式,什么玩意?望着好基友疑惑的眼神,你推了推眼镜,开启了教学模式。
什么是策略模式?
策略模式是指不同类之间有相同的行为,但是行为的具体表现形式又互不相同,在运行时可以动态选择具体要执行的行为的模式。以小刘的业务场景为例,各种促销活动互不相同,但是他们又有一个共同的行为——让商品价格降低,但是每个活动的计算方法又不相同。
设想,如果不使用策略模式,当用户选择参加某种活动后,我们的代码中将会出现一系列的判断,如果是使用优惠券,那么根据优惠券规则计算商品价格,如果是参加打折促销,那么根据打折促销规则计算商品价格,如果是参加满减活动,那么根据满减活动规则计算商品价格。。。这样无疑是灾难性的。
那来看看用策略模式,这种场景将如何实现。
策略模式中,有三个基本角色:
- strategy:抽象策略角色,定义了共同的行为(计算商品价格)。
- concreteStrategy:具体的策略类,需要实现strategy,并重写自己的行为方法。
- contextStrategy:策略上下文,持有策略角色,供客户端调用。
我们按照这三种角色在代码中实现一下。
1、定义策略角色接口strategy
我这里用的接口形式,当然也可以用抽象类。
2、定义具体的策略类
在这个场景中,我们定义三个促销活动的策略类,分别是优惠券活动、折扣活动、满减活动。
优惠券策略类
折扣活动策略类
满减活动策略类
3、定义上下文
上下文策略类中,会持有策略类,并能够执行策略的行为方法
4、测试
假设用户参加了折扣活动,那在我们的上下文策略类中,我们将选择的折扣策略传入,然后再执行,就会直接在折扣策略类中执行相应的计算。
以上就是一个简单的策略模式的实现过程。使用这种方式,将每个策略的实现方式对外隐藏,而是通过上下文去执行具体的策略方法,如果需要进行扩展,也不需要修改上下文,只需将新增的策略类加上即可,通过上下文去进行调用,很容易对代码进行维护。
策略模式与工厂模式的渊源
了解工厂模式的同学可能会有些疑惑(不了解的同学可以查看另一篇文章设计模式之工厂模式——要的是工厂而不是作坊,这与工厂模式也太像了吧。是的,策略模式与工厂模式在代码结构上是非常相似的,而且上文中提到的业务场景,使用工厂模式,也是可以实现的。只不过使用工厂模式,我们首先拿到的是目标对象,拿到目标对象后,再去执行对应的方法,而策略模式,则是直接去执行目标方法。这两个模式的侧重点是不同的,一个是侧重于生成对象,一个是侧重于实现行为。
实际上,策略模式往往要结合工厂模式进行使用。在上文的测试方法中,我们直接把折扣策略类new出来去执行策略方法,而在实际应用中,客户端调用不可能将一个对象传过来,往往是传一个类型代码,或者数字,比如传数字1表示优惠券,传数字2表示折扣,传数字3表示满减,我们在拿到数字后,可以结合工厂模式获取具体的策略类的对象,再通过策略模式执行目标方法,这样在整体的结构上,就会比较清晰。