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)对客户隐藏具体策略(算法)的实现细节,封装性更好,数据更安全。
策略模式的缺点:
随着策略数量的增加,具体实现子类会变得越来越多。