6、策略模式(Strategy Pattern)
1. 策略模式解释
1.1 简介
策略模式是对算法的包装,把使用算法的责任和算法本身分隔开,委派给不同的对象管理。策略模式通常把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。
一个类的行为或其算法可以在运行时更改,这种类型的设计模式属于行为型模式,策略模式就属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
1.2 解释
策略模式uml:
策略模式的三个角色:
- 环境(Context)角色:持有一个Strategy的引用。
- 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
2 策略模式实现
2.1 实现示例
例如从北京去上海旅行,我们由多种出行方式,我们可以做火车、飞机或自驾。不管我们使用哪一种出行方式,最终的目的地都是一样的,也就是选择不同的方式产生的结果都是一样的。
策略接口:
public interface TravelStrategy {
void travelStyle();
}
火车策略实现:
public class TrainStrategy implements TravelStrategy {
@Override
public void travelStyle(){
System.out.println("travel by train!");
}
}
飞机策略实现:
public class PlaneStrategy implements TravelStrategy {
@Override
public void travelStyle(){
System.out.println("travel by plane!");
}
}
自驾策略实现:
public class CarSelfStrategy implements TravelStrategy {
@Override
public void travelStyle(){
System.out.println("drive car!");
}
}
环境实现类:
public class Traveler {
private TravelStrategy travelStrategy;
public Traveler(TravelStrategy travelStrategy) {
this.travelStrategy = travelStrategy;
}
public void travel() {
travelStrategy.travelStyle();
}
}
客户端调用:
public static void main(String[] args) {
TravelStrategy strategy = new PlaneStrategy();
Traveler traveler = new Traveler(strategy);
traveler.travel();
}
策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。
2.2 应用场景
- 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 2、一个系统需要动态地在几种算法中选择一种。
- 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
策略模式优点:
- 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,避免了耦合性太高代码臃肿的现象。
- 策略模式遵循开闭原则,实现代码的解耦合。扩展新的方法时也比较方便,只需要继承策略接口就好了。
策略模式缺点:
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式会出现很多的策略类,策略对象的数目就会很可观。
2.3 与其他模式区别
1、与状态模式的区别
策略模式只是条件选择方法,只执行一次方法,而状态模式是随着状态的改变不停地更改执行方法。举个例子,就好比我们旅游,对于策略模式我们只需要选择其中一种出行方法就好了,但是状态模式不一样,可能我们到了A地点选择的是火车,到了B地点又选择飞机,根据不同的状态选择不同的出行方式。
2、与工厂模式的区别
工厂模式是创建型模式 ,它关注对象创建,提供创建对象的接口,让对象的创建与具体的使用客户无关。 策略模式是对象行为型模式 ,它关注行为和算法的封装 。再举个例子,还是我们出去旅游,对于策略模式我们只需要选择其中一种出行方法就好,但是工厂模式不同,工厂模式是你决定哪种旅行方案后,由工厂代替你去构建具体方案(工厂代替你去买火车票)。
3. 策略模式扩展
在一个使用策略模式的系统中,当存在的策略很多时,客户端管理所有策略算法将变得很复杂。一般策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。例如在环境类中使用策略工厂模式来管理这些策略类将大大减少客户端的工作复杂度,其结构图如下所示:
Strategy Factory uml.gif在上图是简单工厂模式(map实现)和策略模式混用,届时环境实现类不再持有Strategy,而是持有StrategyFactory,根据strategyMethod拿到Strategy,所有Strategy均有StrategyFactory管理。