设计模式篇——策略模式
一、应用场景
1.1 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
1.2 一个系统需要动态地在几种算法中选择一种。
1.3 如果一个对象有很多的行为,如果不用恰当的设计模式,这些行为就只好使用多重的if条件选择语句来实现。
二、介绍
定义:
定义了算法族,分别封装起来,让他们之间可以互相替换,此模式的变化独立于算法的使用者
主要解决:
在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
策略模式涉及到三个角色:
- Strategy:策略接口或者策略抽象类,用来约束一系列的策略算法(Context 使用这个接口来调用具体的策略实现算法)
- ConcreateStrategy:具体的策略类(实现策略接口或继承抽象策略类)
- Context:上下文类,持有具体策略类的实例,并负责调用相关的算法
三、实现
假设我们目前有这样一个场景:我们要出门旅游,此时需要选择交通工具
传统写法:
/**
* @author jiangfeilong
*/
public class Main {
public static void main(String[] args) {
System.out.println("准备旅游,开始选择交通工具。。。");
int i = new Scanner(System.in).nextInt();
if (i == 1) {
System.out.println("选择了私家车");
} else if (i == 2) {
System.out.println("选择了火车");
} else if (i == 3) {
System.out.println("选择了飞机");
}
}
}
策略模式改造后:
/**
* @author jiangfeilong
*/
public class Main {
public static void main(String[] args) {
System.out.println("准备旅游,开始选择交通工具。。。");
//这里就把三种交通工具直接封装好,供调用者直接选择,避免了多重if...else
SelectVehicleContext car = new CarVehicleContext();
SelectVehicleContext train = new TrainVehicleContext();
SelectVehicleContext airplane = new AirplaneVehicleContext();
//选择私家车
car.select();
}
}
/**
* 交通工具抽象
*/
interface VehicleStrategy {
/**
* 选择的实际交通工具
*/
void vehicle();
}
/**
* 选择交通工具
*/
abstract class SelectVehicleContext {
public SelectVehicleContext(VehicleStrategy vehicleStrategy) {
this.vehicleStrategy = vehicleStrategy;
}
protected VehicleStrategy vehicleStrategy;
abstract void select();
}
/**
* 私家车
*/
class CarVehicleContext extends SelectVehicleContext {
/**
* 这里提供一个默认的解决方案
*/
public CarVehicleContext() {
super(() -> System.out.println("选择私家车出行"));
}
public CarVehicleContext(VehicleStrategy vehicleStrategy) {
super(vehicleStrategy);
}
@Override
void select() {
//这里具体选择的交通工具就看用户传递什么交通工具
//这里也可以根据不同的实现类需求,写不同业务逻辑
vehicleStrategy.vehicle();
}
}
/**
* 火车
*/
class TrainVehicleContext extends SelectVehicleContext {
public TrainVehicleContext() {
super(() -> System.out.println("选择火车出行"));
}
public TrainVehicleContext(VehicleStrategy vehicleStrategy) {
super(vehicleStrategy);
}
@Override
void select() {
vehicleStrategy.vehicle();
}
}
/**
* 飞机
*/
class AirplaneVehicleContext extends SelectVehicleContext {
public AirplaneVehicleContext() {
super(() -> System.out.println("选择飞机出行"));
}
public AirplaneVehicleContext(VehicleStrategy vehicleStrategy) {
super(vehicleStrategy);
}
@Override
void select() {
vehicleStrategy.vehicle();
}
}
四、总结
看完这个示例是不是感觉非常简单,其实在实际应用过程中,ConcreateStrategy策略类的具体实现过程会根据应用场景的不同而复杂程度也不同,比如一些复杂的应用场景一个支付接口需要提供多种支付渠道,下面将放上几个框架中已经使用到策略模式的应用场景:
Spring中Resource接口
SpringMVC中DispatcherServlet
优点:
结构清晰明了、使用简单直观
耦合度相对而言较低,扩展方便
操作封装也更为彻底,数据更为安全
缺点:
策略类数量会增多,每个策略都是一个类,复用的可能性很小
所有的策略类都需要对外暴露
代码复杂性增高
总而言之任何东西都是有利有弊,希望小伙伴们可以在适合的时机用上它