原文链接:https://mp.weixin.qq.com/s/Wib0Ly45te00HMUnIG-tbg
调用使用对应的责任树
package com.li.myspringbootmybatis.controller;
import com.alibaba.fastjson.JSONObject;
import com.li.myspringbootmybatis.strategy.a.A;
import com.li.myspringbootmybatis.strategy.root.Root;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
/**
* @author lym
*/
@Controller
public class TestException {
@Resource
private Root root;
@GetMapping("/testStrategy")
@ResponseBody
public void test(){
//root节点中传入参数获取A的处理策略
root.applyStrategy("A");
}
}
1. 创建AbstractStrategyRouter(将文章中的抽象类复制到文本编辑中即可)
package com.li.myspringbootmybatis.strategy;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Objects;
/**
* 通用的“策略树“框架,通过树形结构实现分发与委托,每层通过指定的参数进行向下分发委托,直到达到最终的执行者。
* 该框架包含两个类:{@code StrategyHandler} 和 {@code AbstractStrategyRouter}
* 其中:通过实现 {@code AbstractStrategyRouter} 抽象类完成对策略的分发,
* 实现 {@code StrategyHandler} 接口来对策略进行实现。
* 像是第二层 A、B 这样的节点,既是 Root 节点的策略实现者也是策略A1、A2、B1、B2 的分发者,这样的节点只需要
* 同时继承 {@code StrategyHandler} 和实现 {@code AbstractStrategyRouter} 接口就可以了。
*
* <pre>
* +---------+
* | Root | ----------- 第 1 层策略入口
* +---------+
* / \ ------------- 根据入参 P1 进行策略分发
* / \
* +------+ +------+
* | A | | B | ------- 第 2 层不同策略的实现
* +------+ +------+
* / \ / \ --------- 根据入参 P2 进行策略分发
* / \ / \
* +---+ +---+ +---+ +---+
* |A1 | |A2 | |B1 | |B2 | ----- 第 3 层不同策略的实现
* +---+ +---+ +---+ +---+
* </pre>
*
* @author
* @date
* @see StrategyHandler
*/
@Component
public abstract class AbstractStrategyRouter<T, R> {
/**
* 策略映射器,根据指定的入参路由到对应的策略处理者。
*
* @param <T> 策略的入参类型
* @param <R> 策略的返回值类型
*/
public interface StrategyMapper<T, R> {
/**
* 根据入参获取到对应的策略处理者。可通过 if-else 实现,也可通过 Map 实现。
*
* @param param 入参
* @return 策略处理者
*/
StrategyHandler<T, R> get(T param);
}
private StrategyMapper<T, R> strategyMapper;
/**
* 类初始化时注册分发策略 Mapper
*/
@PostConstruct
private void abstractInit() {
strategyMapper = registerStrategyMapper();
Objects.requireNonNull(strategyMapper, "strategyMapper cannot be null");
}
@Getter
@Setter
@SuppressWarnings("unchecked")
private StrategyHandler<T, R> defaultStrategyHandler = StrategyHandler.DEFAULT;
/**
* 执行策略,框架会自动根据策略分发至下游的 Handler 进行处理
*
* @param param 入参
* @return 下游执行者给出的返回值
*/
public R applyStrategy(T param) {
final StrategyHandler<T, R> strategyHandler = strategyMapper.get(param);
if (strategyHandler != null) {
return strategyHandler.apply(param);
}
return defaultStrategyHandler.apply(param);
}
/**
* 抽象方法,需要子类实现策略的分发逻辑
*
* @return 分发逻辑 Mapper 对象
*/
protected abstract StrategyMapper<T, R> registerStrategyMapper();
}
2. 创建策略处理器接口
package com.li.myspringbootmybatis.strategy;
/**
* @author
* @date
*/
public interface StrategyHandler<T, R> {
@SuppressWarnings("rawtypes")
StrategyHandler DEFAULT = t -> null;
/**
* apply strategy
*
* @param param
* @return
*/
R apply(T param);
}
3. 开始构建对应的节点信息
* +---------+ * | Root | ----------- 第 1 层策略入口 * +---------+ * / \ ------------- 根据入参 P1 进行策略分发 * / \ * +------+ +------+ * | A | | B | ------- 第 2 层不同策略的实现 * +------+ +------+ * / \ / \ --------- 根据入参 P2 进行策略分发 * / \ / \ * +---+ +---+ +---+ +---+ * |A1 | |A2 | |B1 | |B2 | ----- 第 3 层不同策略的实现 * +---+ +---+ +---+ +---+
4. 创建Root
package com.li.myspringbootmybatis.strategy.root;
import com.li.myspringbootmybatis.strategy.AbstractStrategyRouter;
import com.li.myspringbootmybatis.strategy.StrategyHandler;
import com.li.myspringbootmybatis.strategy.a.A;
import com.li.myspringbootmybatis.strategy.b.B;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Component
public class Root extends AbstractStrategyRouter<String,Boolean> {
@Resource
private A a;
@Resource
private B b;
/**
* 定义用来存储执行策略的map集合
*/
private Map<String,StrategyHandler> strategyMap = new HashMap();
/**
* 创建某个节点下的策略或节点
* @return
*/
@Override
protected StrategyMapper<String,Boolean> registerStrategyMapper() {
strategyMap.put("A",a);
strategyMap.put("B",b);
return new RootStrategyMapperImpl();
}
/**
* 实现父类定义的接口,用于实现自己的获取不同的策略
* 就像文章中所说,可以写if也可以写map,在这我们使用的是map
*/
class RootStrategyMapperImpl implements StrategyMapper<String,Boolean>{
@Override
public StrategyHandler<String,Boolean> get(String param) {
return strategyMap.get(param);
}
}
}
5. 创建A
package com.li.myspringbootmybatis.strategy.a;
import com.li.myspringbootmybatis.strategy.AbstractStrategyRouter;
import com.li.myspringbootmybatis.strategy.StrategyHandler;
import com.li.myspringbootmybatis.strategy.b.B;
import com.li.myspringbootmybatis.strategy.root.Root;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class A extends AbstractStrategyRouter<String,Boolean> implements StrategyHandler<String, Boolean> {
/**
* 定义用来存储执行策略的map集合
*/
private Map<String,StrategyHandler> strategyMap = new HashMap();
@Override
protected StrategyMapper<String,Boolean> registerStrategyMapper() {
strategyMap.put("A1",new A1());
strategyMap.put("A2",new A2());
return new AStrategyMapperImpl(strategyMap);
}
/**
* 实现自己获取 对应的策略信息
*/
class AStrategyMapperImpl implements StrategyMapper<String,Boolean>{
private Map<String,StrategyHandler> strategyMap1;
AStrategyMapperImpl(Map map){
strategyMap1 = map;
}
@Override
public StrategyHandler<String,Boolean> get(String param) {
return strategyMap1.get(param);
}
}
@Override
public Boolean apply(String param) {
System.out.println("A执行。。。。");
System.out.println("A执行完毕");
//用于责任链调用,传递执行A1策略
this.applyStrategy("A1");
return true;
}
}
6. 创建A1节点
package com.li.myspringbootmybatis.strategy.a;
import com.li.myspringbootmybatis.strategy.StrategyHandler;
import org.springframework.stereotype.Component;
@Component
public class A1 implements StrategyHandler<String,Boolean> {
@Override
public Boolean apply(String param) {
System.out.println("A1开始执行");
System.out.println("A1开始完毕");
return true;
}
}