深入理解策略模式:概念、环境类与具体策略类的应用解析
[id_1708901960]

[id_1457369921]
环境类是使用算法的角色。它在解决某个问题时,也就是在实现某个方法时,可以运用多种策略。在环境类里维持着一个对抽象策略类的引用实例,这个引用实例用于定义所采用的策略。
策略类:它对所支持的算法进行了抽象方法的声明,是所有策略类的父类。它可以是抽象类,也可以是具体类,还可以是接口。在运行时,环境类会通过抽象策略类中声明的方法来调用具体策略类中实现的算法。
具体策略类:它把抽象策略类中声明的算法给实现了。在运行的过程当中,具体策略类会把环境类中所定义的抽象策略类对象给覆盖掉,然后利用一种具体的算法来完成某个业务的处理。
2、白话理解
做一批相机时,分配中心需要依据相机的类型去找到相应的工人来制作相机。
在这个例子中
二、代码中看策略模式 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、将策略模式引入进来。
设计一个抽象类 CameraStrategy 。这个抽象类中有两个方法,一个是返回类型的方法,另一个是实际生产相机的方法。
/**
* 相机
**/
public abstract class CameraStrategy {
/**
* 支持的相机种类
* @return
*/
public abstract Integer supportedCameraType();
/**
* 生产相机
* */
public abstract void productionCamera();
}
在两个实际用于生产相机的子类里把这两个方法给实现了。然后把具体的实现逻辑给返回出来。
/**
* 数码相机工种
**/
public class DigitalCameraStrategy extends CameraStrategy{
@Override
public Integer supportedCameraType() {
// 数码相机type为1
return 2;
}
@Override
public void productionCamera() {
System.out.println("数码相机工作中");
}
}
/**
* 单反相机工种
**/
public class SLRCameraStrategy extends CameraStrategy {
@Override
public Integer supportedCameraType() {
// 单反相机type为1
return 1;
}
@Override
public void productionCamera() {
System.out.println("数码相机工作中");
}
}
在特定的情境(context)里管理相机工种,对于不同的相机类型,能够获取到与之对应的不同工种去进行工作。
/**
* 分配中心
**/
@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);
}
}
使用者需要清楚知晓所有的策略类以及它们的用途;