springboot的策略模式

  张一帆   2021年05月02日


策略模式的目的是将不同的策略封装起来,每个策略形成一个一个类文件。你可以进行任意的替换。策略模式遵循开闭原则,意即对扩展保持开放,对修改保持关闭。

当你用springboot的时候,会牵扯到如何将类委托给spring容器,如果你按照策略模式的传统写法,就会遇到类似问题。所以,我们应该将不同的策略实现公用的接口,也就是面向接口编程。

首先,我们定义一个接口。

public interface ICreateOrderAndMissionStrategy {

	/**
	 * 创建订单和任务。不同的策略应该对这个方法进行重写
	 */
	void doCreateOrderAndMission(KCameraOrderAbstractCreateDTO oscVo);

	/**
	 * 获取类型,每个策略都需要你定义一个类型,比如业务1就定义为1,比如业务2就定义为2。当然,你也可以定义成不同类型。按照你的习惯即可
	 * @return Integer
	 */
	Integer getType();
}

然后,构造一个类,这个类的目的就是驱动你的策略。同时,也是这个类将你的策略装配到spring中。

@Service
public class CreateOrderMissionStrategyService {

	/**
	 * 策略类中的成员map变量,保存各种策略类.可以看到我将ICreateOrderAndMissionStrategy接口构造成一个map。通过我之前定义的数字来获取value。也就是能够拿到相应的策略。
	 */
	Map<Integer, ICreateOrderAndMissionStrategy> strategyMap = new HashMap<>(8);

	/**
	 * 构造函数,通过将spring管理的所有策略类注册进成员map变量中。
	 * 这个方法很重要,因为它驱动了策略类的装配。
	 * @param strategies List<ICreateOrderAndMissionStrategy>
	 */
	public CreateOrderMissionStrategyService(List<ICreateOrderAndMissionStrategy> strategies) {
		for (ICreateOrderAndMissionStrategy strategy : strategies) {
			strategyMap.put(strategy.getType(), strategy);
		}
	}

	/**
	 * 处理策略程序。通过strategyType得到我想要的策略类,然后进行调用
	 * @param strategyType 策略类型
	 * @param oscVo 业务变量
	 * @throws BizException 业务异常
	 */
	public void executeStrategy(Integer strategyType, KCameraOrderAbstractCreateDTO oscVo) throws BizException{
		ICreateOrderAndMissionStrategy strategy = strategyMap.get(strategyType);
		if(strategy == null){
			throw new BizException("未找到事件处理实现类,strategyType:" + strategyType);
		}
		strategy.doCreateOrderAndMission(oscVo);
	}
}

现在,我可以开始根据不同的业务进行不同的策略了。我举两个例子。

//这个是策略A
public class AStrategy implements ICreateOrderAndMissionStrategy {

    @Override
	public Integer getType() {
		return BizEnum.A.getCode();  // 这个是我定义的策略类型的枚举类。我A为1,B为2
	}
	
	/**
	 * A策略的实现逻辑
	 */
	@Override
	public void doCreateOrderAndMission(ParamDTO paramDTO) {
	   .........
	}
}
//这个是策略B
public class BStrategy implements ICreateOrderAndMissionStrategy {

    @Override
	public Integer getType() {
		return BizEnum.B.getCode();  	}
	
	/**
	 * B策略的实现逻辑
	 */
	@Override
	public void doCreateOrderAndMission(ParamDTO paramDTO) {
	   .........
	}
}

在真正的逻辑中,我们就可以直接使用这个模式了。

public class Demo{

    public void Business(){
        String[] taskTypeList = oscVo.getTaskTypes().split(",");
			for (String i : taskTypeList) {
    createHouseSourceOrderAndMission.executeStrategy(Integer.valueOf(i),oscVo);
            			}
    }
}