1. 关于策略模式
策略模式和java语言的多态特性有些像。java的多态特性允许我们面向接口编程,不用关心接口的具体实现。接口所指向的实现类,以及通过接口调用的方法的具体行为可以到运行时才绑定。这么做最大的好处是在尽可能实现代码复用的前提下更好地应对具体实现类的变化。比如我想增加一种接口的实现或者修改原有实现类的某个行为,那我几乎不用修改任何客户端代码。策略模式可以说正是这种思想在设计模式上的运用。它可以使我们更好的复用代码,同时使程序结构设计更有弹性,更好的应对变化。
2. 策略模式详解 2.1 策略模式定义 策略模式定义了一系列算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户端而独立的变化。可以使用多态进行类比来理解策略模式的定义。一系列算法可以理解成接口的不同实现类,因为不同实现类都实现了相同的接口,因而它们也可以相互替换。策略模式让算法独立于客户端而变化与接口的实现类可以独立于使用接口的客户端变化类似。
2.2 策略模式的UML类图从UML类图上可以看出,策略模式中主要有3个角色
抽象策略接口
上图中的Strategy即抽象策略接口,接口中定义了抽象的策略算法algorithm()。
具体的策略实现类
上图中的StrategyA和StrategyB即具体的策略实现。不同的策略实现类都实现了抽象策略接口,并重写了其抽象策略方法。因为都实现了相同的策略接口,因而算法可以相互替换,并且可以动态的改变具体的算法实现。
封装策略的上下文环境
上图中的Context即策略的上下文环境。它屏蔽了高层模块对策略算法的直接访问,封装了可能存在的变化。而且提供了修改Strategy的setter方法,可以动态的改变算法的具体实现。
我们可以结合使用策略模式的例子并与其它实现方案进行对比来看看策略模式到底有什么好处
3.1 一个使用策略模式的例子定义一个汽车类Car。由于汽车最大的特点是能跑,因而我们赋予该类一个move行为。但要跑起来需要提供能源,通常而言这种能源是汽油,但现在纯靠电池驱动的汽车也越来越多。因而Car的move行为就有两种不同的行为,一种是使用汽油跑,一种是使用电能跑。因而我们可以这么定义
抽象的汽车类Car
/**
* @author: takumiCX
* @create: 2018-10-13
**/
public abstract class Car {
//汽车品牌
private String brand;
public Car(String brand) {
this.brand = brand;
}
public Car(String brand, MoveStrategy strategy) {
this.brand = brand;
this.moveStrategy=strategy;
}
//汽车的运行策略:使用汽油运行,使用电能运行等等
private MoveStrategy moveStrategy;
//运行方法
public void move() {
System.out.print(brand);
moveStrategy.move();
}
public void setMoveStrategy(MoveStrategy moveStrategy) {
this.moveStrategy = moveStrategy;
}
}
在抽象汽车类中定义了一个move()方法表示汽车具有运行的行为,但是由于到底是使用汽油运行还是使用电能运行并没有直接定义在里面,而是调用了策略接口中定义的move方法。该策略接口以组合的方式封装在Car内部,并提供了setter方法供客户端动态切换汽车的运行方式。
使用汽油运行的策略实现
/**
* @author: takumiCX
* @create: 2018-10-14
**/
/**
* 使用汽油运行的策略实现
*/
public class GasolineMoveStrategy implements MoveStrategy{
@Override
public void move() {
System.out.println(" Use Gasoline Move!");
}
}
使用电池运行的策略实现
/**
* @author: takumiCX
* @create: 2018-10-15
**/
/**
* 使用电能运行的策略实现
*/
public class ElectricityMoveStrategy implements MoveStrategy {
@Override
public void move() {
System.out.println(" Use Electricity Move!");
}
}
具体的汽车实现类
比如我们通过继承的方式定义一辆特斯拉汽车,特斯拉汽车默认是纯电动的
/**
* @author: takumiCX
* @create: 2018-10-13
**/
public class TeslaCar extends Car {
public TeslaCar(String brand) {
super(brand,new ElectricityMoveStrategy());
}
}
客户端代码
首先构造一辆特斯拉车观察其运行方式,并通过setter方法动态改变其运行方式为汽油驱动
/**
* @author: takumiCX
* @create: 2018-10-13
**/
public class Client {
public static void main(String[] args) {
TeslaCar car = new TeslaCar("Tesla");
car.move();
car.setMoveStrategy(new GasolineMoveStrategy());
car.move();
}
}
运行结果
其实上面的例子除了使用策略模式外,还有其他实现方式,但它们都有比较明显的缺点。
3.2.1接口的实现方式/**
* @author: takumiCX
* @create: 2018-10-15
**/
public interface Move {
void move();
}
并让抽象父类Car实现它