一个超级简单且实用的策略模式。
首先,定义一个抽象的策略处理器
/**
* @author pikadog~
* 抽象处理类
*/
public abstract class AbstractSolver {
/**
*一个处理器可以处理多个类型,用来指定什么情况下会选择当前策略
* @return
*/
public abstract SolverType[] solverTypes();
/**
* 业务逻辑
* @param param
* @return
*/
public Object doSolver(Object param) {
return param;
}
}
策略类型
/**
* @author pikadog~
* 2022/2/28 15:46
*/
public enum SolverType {
ONE( "solver1"),
TWO( "solver1");
private String type;
SolverType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
然后就是用来管理策略的选择器
/**
* @author pikadog~
* 策略处理器的选择器,用来管理处理器
* 相当于一个容器,hashMap
* @date 2022/1/7 11:07
*/
@Component
public class SolverChooser implements ApplicationContextAware {
private final static Map<SolverType, AbstractSolver> CHOOSER_SOLVERS_MAP = new HashMap<>();
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@PostConstruct
public void register() {
/**
* 把所有容器中的处理器收集起来放到map里集中管理
*/
Map<String, AbstractSolver> solverMap = applicationContext.getBeansOfType(AbstractSolver.class);
for (AbstractSolver solver : solverMap.values()) {
for (SolverType type : solver.solverTypes()) {
CHOOSER_SOLVERS_MAP.put(type,solver);
}
}
}
/**
* 根据类型选择策略
* @param type
* @return
*/
public AbstractSolver choose(SolverType type) {
return CHOOSER_SOLVERS_MAP.get(type);
}
}
这里的@PostConstruct也可以换成其他的初始化方法,注意他们的执行顺序,以实现不同的业务需求。
例如@PostConstruct >早于afterPropertiesSet() 早于 initMethod()执行。
具体的处理器
@Component
public class TwoSolver extends AbstractSolver {
@Override
public SolverType[] solverTypes() {
return new SolverType[]{SolverType.ONE,SolverType.TWO};
}
/**
* 实际执行的业务方法
* @param param
* @return
*/
@Override
public Object doSolver(Object param) {
System.out.println("one,two");
return super.doSolver(param);
}
}
@Test
void contextLoads() {
Object o = chooser.choose(SolverType.ONE).doSolver(new TUser());
Object o2 = chooser.choose(SolverType.TWO).doSolver(new TUser());
}
//此时都会输出one,two
也可以把选择器和抽象处理器放一起
public abstract class SolverChooserAndDo {
private final static Map<String, SolverChooserAndDo> HASH_MAP = new HashMap<>();
public static SolverChooserAndDo getServiceType(String serviceType) {
return HASH_MAP.get(serviceType);
}
/**
* 策略的key,用来将服务类注册进HASH_MAP
*
* @return String
*/
public abstract String serviceType();
@PostConstruct
public void init() {
put(this.serviceType(), this);
}
private void put(String serviceKey, SolverChooserAndDo service) {
HASH_MAP.put(serviceKey, service);
}
/**
* 具体逻辑
* @param param
*/
public abstract void sendAward(Object param);
/**
* 多个具体业务逻辑
* @param param
*/
public abstract void check(Object param);
}
用法和逻辑都是一样的 这样写比较简单。
可以考虑把抽象处理器和选择器的参数换成泛型,这样每个业务逻辑就不用再写一套选择器和抽象处理器了。