策略模式(Strategy)的定义:定义一系列的算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响客户端的调用。属于行为型模式。
策略模式的本质是通过对算法的封装,把算法的使用和算法的实现隔离,并委派给不同的对象对这些算法进行分别管理。
策略模式的结构:策略模式主要有3种角色。
- 抽象策略(Strategy)类:定义了一个公共接口,规定策略或算法的行为方法,一般使用接口或抽象类实现。
- 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
- 上下文环境(Context)类:供客户端调用的类,持有一个策略类的引用,委派给策略类进行实际业务处理。
策略模式的通用实现:
//抽象策略类
public interface Strategy {
void strategyMethod();
}
//具体策略A
public class ConcreteStrategyA implements Strategy{
@Override
public void strategyMethod() {
System.out.println("执行具体策略A的策略方法!");
}
}
//具体策略B
public class ConcreteStrategyB implements Strategy{
@Override
public void strategyMethod() {
System.out.println("执行具体策略B的策略方法!");
}
}
//上下文环境类
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public void strategyMethod() {
strategy.strategyMethod();
}
}
//测试类
public class StrategyTest {
public static void main(String[] args) {
Context contextA = new Context(new ConcreteStrategyA());
contextA.strategyMethod();
Context contextB = new Context(new ConcreteStrategyB());
contextB.strategyMethod();
}
}
策略模式的结构图:
策略模式的应用实例:现在交通发达,给我们的出行带来了极大的便利,我们可以选择飞机、火车、汽车等等,我们就以出行的交通方式为例,使用策略模式来实现。
//交通方式接口
public interface ITransport {
void goOut();
}
//飞机
public class Plane implements ITransport{
@Override
public void goOut() {
System.out.println("远距离出行,选择飞机!!!");
}
}
//火车
public class Train implements ITransport{
@Override
public void goOut() {
System.out.println("中等距离出行,选择高铁!!!");
}
}
//汽车
public class Car implements ITransport{
@Override
public void goOut() {
System.out.println("近距离出行,选择汽车!!!");
}
}
//出行方式枚举类
public enum TransportType {
CAR, TRAIN, PLANE;
}
//策略管理类
public class TransportStrategy {
private static Map<TransportType, ITransport> strategy = new HashMap<>();
static {
strategy.put(TransportType.CAR,new Car());
strategy.put(TransportType.TRAIN,new Train());
strategy.put(TransportType.PLANE,new Plane());
}
public ITransport getTransport(TransportType transportType){
if(transportType == null){
throw new RuntimeException("交通方式选择有误!");
}
return strategy.get(transportType);
}
}
//测试类
public class Test {
public static void main(String[] args) {
TransportStrategy strategy = new TransportStrategy();
ITransport transport = strategy.getTransport(TransportType.PLANE);
transport.goOut();
}
}
策略模式在源码中的应用:Jdk中的Comparator比较器接口、Spring中的Resource接口都是采用的策略模式实现的。
策略模式的优点:
- 使用策略模式可以避免使用多重条件语句,如 if...else 语句、switch...case 语句。
- 策略模式可以把算法族的公共代码转移到父类中实现,提高代码复用性。
- 策略模式可以在不修改原代码的情况下,灵活增加新算法,符合开闭原则。
- 策略模式把算法的使用和实现隔离,提高算法的保密性和安全性。
策略模式的缺点:
- 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
- 策略模式造成很多的策略类,增加维护难度。
策略模式的使用场景:
- 同一类型问题有多种独立的处理算法,可将每个算法封装到策略类中。
- 系统中各算法彼此独立,且要求对客户端隐藏具体算法的实现细节。