0. 前言
写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇效哦~
此篇总结整理设计模式中的策略模式。
1. 策略模式介绍
策略模式定义:
策略模式定义了一系列算法,通过实现同一个接口将每一个算法封装起来,这样在客户端就可以通过注入不同的实现对象来实现算法/策略的动态替换。
策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。
策略模式的使用场景:
(1)针对同一类型问题,有多种具体的处理方式时。 即多个类只区别在表现行为不同,在运行时动态选择具体要执行的行为。并且还可能在未来用其它方式来实现。
(2)需要对客户隐藏具体策略(算法)的实现细节时。
策略模式角色介绍:
(1)Stragety类:策略的抽象类或接口类。所有的具体策略类都有一些公有的行为,这些公有的行为被抽象到Strategy类里。
(2)ConcreteStragety类:具体的策略实现类。
(3)Context类:持有一个策略类引用的上下文环境。
2 实例介绍
在本例中,我们使用“选择出行方案”的案例,其中,我们可以选择乘坐“出租车”、“地铁”或者是“公交车”。之所以选择这个案例,因为每种出行方案都有自己的费用算法。比如出租车,有个起步价,多坐一公里是多少钱等等。具体的算法不是我们关心的。
2.1传统的实现方案
对于上述案例,我们很容易想到在客户端中,传给价格工具类路程的距离以及出行方式,工具类中分别实现这三种出行方式的费用算法(用三个方法实现),拿到客户端传来的参数后,通过if/else判断是哪种出行方式,再将距离参数传入对应的计算费用的方法,获取到返回值,最后返回给客户端。
上述解决方案缺点非常明显:这类代码难以应对变化,在添加出行方式时,我们需要手动添加if/else,代码会变得越来越臃肿且难以维护。策略模式解决的就是此类问题。
3 使用策略模式解决问题
3.1 Stragety接口类
public interface Stragety{ int calculateMoney(int distance); }
3.2 Stragety接口实现类
/* *@author SEU_Calvin *@date 2016/09/06 */ public class TaxiStragety implements Stragety{ @override public int calculateMoney(int distance){ //出租车具体计价算法,参数为出行距离 } } public class SubwayStragety implements Stragety{ @override public int calculateMoney(int distance){ //地铁具体计价算法,参数为出行距离 } }
3.3 Context类
/* *@具体使用类 *@author SEU_Calvin *@date 2016/09/06 */ public class Test{ public static void main(String[] args){ Test calculator = new Test(); //设置出租车出行策略 calculator.setStrategy(new TaxiStrategy); //计算价格 System.out.println("出行20公里的费用为==>" + calculator. calculateMoney(20)); } Stragety mStragety; public void setStrategy(Stragety mStragety){ this..mStragety = mStragety; } public int calculateMoney (int distance){ return mStragety. calculateMoney(distance); } }
4 策略模式的优缺点
策略模式的优点:
(1)结构清晰,降低了耦合度,易于拓展。上例中如果需要再添加一种出行方式,只需要修改较少的已有代码。
(2)对客户隐藏具体策略(算法)的实现细节,封装性更好,数据更安全。
策略模式的缺点:
随着策略数量的增加,具体实现子类会变得越来越多。