责任链模式
前言
前几天做了一个需求,业务中需要进行校验,全部满足才能允许进行下一步动作。校验过程如A->B->C,这个业务逻辑适合用一个责任链的模式去实现。
一、责任链模式是什么
百度百科上面解释,责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
二、样例实现
1.需求目的
业务所需要求大致如下图
2.代码展示
这里我用修身,齐家,治国,平天下这个儒家的思想来展示样例,对每条链的都有年龄做判断处理。
核心代码:
public boolean doLifeHandler(LifeThoughtVo lifeThoughtVo){
LifeEnum lifeEnum = LifeEnum.getFirstChain();
AbstractLifeHandler abstractLifeHandler = abstractLifeHandlerMap.get(lifeEnum.getServerName());
boolean doLifeResult = false;
while (abstractLifeHandler != null && (doLifeResult = abstractLifeHandler.doLifeHandler(lifeThoughtVo))) {
abstractLifeHandler = abstractLifeHandler.nextHandler;
}
return doLifeResult;
}
构建责任链中对象和关系链,这里使用@Autowired可以直接将继承同一个抽象类的bean注入到map中。构建链的顺序,代码如下。
@Service
public class LifeThoughtService {
@Autowired
private Map<String, AbstractLifeHandler> abstractLifeHandlerMap;
@PostConstruct
public void initAbstractLifeHandler(){
LifeEnum lifeEnum = LifeEnum.getFirstChain();
if (lifeEnum==null){
return;
}
AbstractLifeHandler abstractLifeHandler = abstractLifeHandlerMap.get(lifeEnum.getServerName());
while ((lifeEnum=(LifeEnum.getLifeEnumByHandlerId(lifeEnum.getNextHandlerId())))!=null){
AbstractLifeHandler nextAbstractLifeHandler = abstractLifeHandlerMap.get(lifeEnum.getServerName());
abstractLifeHandler.setNextHandler(nextAbstractLifeHandler);
abstractLifeHandler = nextAbstractLifeHandler;
}
}
public boolean doLifeHandler(LifeThoughtVo lifeThoughtVo){
LifeEnum lifeEnum = LifeEnum.getFirstChain();
AbstractLifeHandler abstractLifeHandler = abstractLifeHandlerMap.get(lifeEnum.getServerName());
boolean doLifeResult = false;
while (abstractLifeHandler != null && (doLifeResult = abstractLifeHandler.doLifeHandler(lifeThoughtVo))) {
abstractLifeHandler = abstractLifeHandler.nextHandler;
}
return doLifeResult;
}
}
调用链的先后顺序枚举类如下:
@Getter
public enum LifeEnum {
SELF_CULTIVATION("1", "修身", "selfCultivationServiceHandler", "2"),
FAMILY_UNITY("2", "齐家", "familyUnityServiceHandler", "3"),
GOVERNANCE("3", "治国", "governanceServiceHandler", "4"),
WORLD_PEACE("4", "平天下", "worldPeaceServiceHandler", "null");
private final String handlerId;
private final String name;
private final String serverName;
private final String nextHandlerId;
private LifeEnum(String handlerId, String name, String serverName, String nextHandlerId) {
this.handlerId = handlerId;
this.name = name;
this.serverName = serverName;
this.nextHandlerId = nextHandlerId;
}
public static LifeEnum getFirstChain() {
return SELF_CULTIVATION;
}
public static LifeEnum getLifeEnumByHandlerId(String handlerId) {
if (StringUtils.isEmpty(handlerId)) {
return null;
}
for (LifeEnum lifeEnum : values()) {
if (handlerId.equals(lifeEnum.getHandlerId())) {
return lifeEnum;
}
}
return null;
}
}
spring容器已经对bean进行管理了,在这里只需要将bean之间的先后顺序进行维护,构建成一条链的处理形式,即可。
责任链抽象类如下:
public abstract class AbstractLifeHandler {
protected AbstractLifeHandler nextHandler;
public void setNextHandler(AbstractLifeHandler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract boolean doLifeHandler(LifeThoughtVo lifeThoughtVo);
}
其中某个实现service如下:
@Service
@Slf4j
public class SelfCultivationServiceHandler extends AbstractLifeHandler {
@Override
public boolean doLifeHandler(LifeThoughtVo lifeThoughtVo) {
if (lifeThoughtVo.getSelfCultivationAge() < 18) {
log.info("SelfCultivationService年龄限制");
return false;
}
log.info("SelfCultivationService pass");
return true;
}
}
责任链模式的内容已经实现,下面展示测试后的结果,可以看到,按枚举类中顺序输出了想要的结果。实际上针对不对业务需求在此基础上进行改动即可。
总结
责任链模式在很多场景上都可以使用到,能够对业务代码进行解耦,方便增删业务功能。如果想要动态的控制链条中执行的流程,可以将枚举的先后顺序引入到配置发布中,通过配置去动态控制更加灵活。