目录
- 一、认识策略模式
- 1、概念
- 2、白话理解
- 二、代码中看策略模式
- 1、没有策略模式怎么写
- 2、引入策略模式
- 三、策略模式的优缺点
- 优点
- 缺点
一、认识策略模式
1、概念
Context(环境类):环境类是使用算法的角色,它在解决某个问题(即实现某个方法)时可以采用多种策略。在环境类中维持一个对抽象策略类的引用实例,用于定义所采用的策略。
Strategy(抽象策略类):它为所支持的算法声明了抽象方法,是所有策略类的父类,它可以是抽象类或具体类,也可以是接口。环境类通过抽象策略类中声明的方法在运行时调用具体策略类中实现的算法。
ConcreteStrategy(具体策略类):它实现了在抽象策略类中声明的算法,在运行时,具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务处理。
2、白话理解
实际例子:做一批相机,分配中心需要根据相机的类型去找到不同的工人做相机。
在这个例子中
- 分配中心就是 context
- 具体做相机的工种就是ConcreteStrategy
二、代码中看策略模式
1、没有策略模式怎么写
/**
* 生产相机
* */
public void productionCamera(Camera camera) {
if (camera.getType().equals(1)) {
System.out.println("生产单反相机");
}
if (camera.getType().equals(2)) {
System.out.println("生产数码相机");
}
}
可能你觉得这么写没毛病。那么我想问三个问题
- 如果说生产相机的逻辑非常长呢?if else会让逻辑非常难读懂
- 如果说后续还有其他其他种类的相机呢?每每增加一种相机都要重新去改代码
- 如果说生产相机的工序很多都是一致的呢?难不成要写重复的代码吗?
2、引入策略模式
1、设计一个抽象类CameraStrategy,其中有两个方法,第一个是返回类型方法,第二个是实际的生产相机方法。
/**
* <p>相机</p>
**/
public abstract class CameraStrategy {
/**
* 支持的相机种类
* @return
*/
public abstract Integer supportedCameraType();
/**
* 生产相机
* */
public abstract void productionCamera();
}
2、在两个实际生产相机的子类中实现这两个方法。返回具体的实现逻辑
/**
* <p>数码相机工种</p>
**/
public class DigitalCameraStrategy extends CameraStrategy{
@Override
public Integer supportedCameraType() {
// 数码相机type为1
return 2;
}
@Override
public void productionCamera() {
System.out.println("数码相机工作中");
}
}
/**
* <p>单反相机工种</p>
**/
public class SLRCameraStrategy extends CameraStrategy {
@Override
public Integer supportedCameraType() {
// 单反相机type为1
return 1;
}
@Override
public void productionCamera() {
System.out.println("数码相机工作中");
}
}
3、在context中管理相机工种,对于不同的相机类型获得到不同的工种去干活
/**
* <p>分配中心</p>
**/
@Component
public class CameraContext {
// 这里使用到了Spring的自动注入,将所有子类注入进来
@Autowired
private List<CameraStrategy> cameraStrategies;
// 不同的工种自己进行不同的逻辑
public void productionCamera(Integer type) {
this.getStrategy(type).productionCamera();
}
// 根据type的不同来获取到不同的工种子类
private CameraStrategy getStrategy(Integer type) {
return this.cameraStrategies
.stream()
.filter(cameraStrategy -> type.equals(cameraStrategy.supportedCameraType()))
.findFirst()
.get();
}
}
4、实际调用方仅需要传入需要创建的相机类型即可完成生产
@RunWith(SpringRunner.class)
public class MyTest {
@Resource
private CameraContext context;
@Test
public void productionTest() {
context.productionCamera(1);
}
}
三、策略模式的优缺点
优点
- 干掉繁琐的 if、switch 判断逻辑;
- 代码优雅、可复用、可读性好;
- 符合开闭原则,扩展性好、便于维护;
缺点
- 策略如果很多的话,会造成策略类膨胀;
- 使用者必须清楚所有的策略类及其用途;