本文最后更新于 1176 天前,其中的信息可能已经有所发展或是发生改变。
责任链模式
定义
在职责链模式中,多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。
在 GoF 的定义中,一旦某个处理器能处理这个请求,就不会继续将请求传递给后续的处理器了。当然,在实际的开发中,也存在对这个模式的变体,那就是请求不会中途终止传递,而是会被所有的处理器都处理一遍。
实现方式
链表
AbstractHandler
public abstract class AbstractHandler {
private AbstractHandler nextHandler;
public void setNextHandler(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
}
public void handle() {
boolean handled = doHandle();
if (!handled && nextHandler != null) {
nextHandler.handle();
}
}
protected abstract boolean doHandle();
}
HandlerA
public class HandlerA extends AbstractHandler {
@Override
protected boolean doHandle() {
boolean result = false;
System.out.println("HandlerA");
return result;
}
}
HandlerB
public class HandlerB extends AbstractHandler {
@Override
protected boolean doHandle() {
boolean result = false;
System.out.println("HandlerB");
return result;
}
}
HandlerChain
public class HandlerChain {
private AbstractHandler head;
private AbstractHandler tail;
public HandlerChain addHandler(AbstractHandler handler) {
if (head == null) {
head = handler;
tail = handler;
} else {
tail.setNextHandler(handler);
tail = handler;
}
return this;
}
public void handle() {
if (head != null) {
head.handle();
}
}
}
Application
public class Application {
public static void main(String[] args) {
final HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA())
.addHandler(new HandlerB())
.handle();
}
}
数组
IHandler
public interface IHandler {
void handle();
}
HandlerA
public class HandlerA implements IHandler {
@Override
public void handle() {
System.out.println("HandlerA");
}
}
HandlerB
public class HandlerB implements IHandler {
@Override
public void handle() {
System.out.println("HandlerB");
}
}
HandlerChain
public class HandlerChain {
private List<IHandler> chain = Lists.newArrayList();
public HandlerChain addHandler(IHandler handler) {
chain.add(handler);
return this;
}
public void handle() {
chain.forEach(IHandler::handle);
}
}
Application
public class Application {
public static void main(String[] args) {
final HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA())
.addHandler(new HandlerB())
.handle();
}
}
优缺点
- 你可以控制请求处理的顺序。
- 单一职责原则。 你可对发起操作和执行操作的类进行解耦。
- 开闭原则。 你可以在不更改现有代码的情况下在程序中新增处理者。
适用场景
当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。
该模式能将多个处理者连接成一条链。 接收到请求后, 它会 “询问” 每个处理者是否能够对其进行处理。 这样所有处理者都有机会来处理请求。
当必须按顺序执行多个处理者时, 可以使用该模式。
无论你以何种顺序将处理者连接成一条链, 所有请求都会严格按照顺序通过链上的处理者。
如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式。
如果在处理者类中有对引用成员变量的设定方法, 你将能动态地插入和移除处理者, 或者改变其顺序。
实战
@ChainNode:标识责任链节点
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ChainNode {
/**
* 所属链名称
*/
String chain();
/**
* 节点名称
*/
String name() default StrUtil.EMPTY;
/**
* 在链中的位置(-1表示末尾)
*/
int index() default -1;
}
- 支持多条责任链
- 支持配置执行顺序
Validate:定义责任链节点的能力
支持多个定义,只有要与之对应的执行器就行
public interface Validate<T> {
/**
* 执行校验
*
* @param context
* @author yuyouyang
* @date 2021/6/3 21:38
* @version 1.0
*/
void doValidate(T context);
}
- 参数和结果都放在context里
ColumnValidate:责任链节点,字段校验
@Component
@ChainNode(chain = ChainConstant.DESIGN_VALIDATE_CHAIN, name = ChainConstant.COLUMN_VALIDATE, index = 1)
public class ColumnValidate implements Validate<Map<String, Object>> {
@Override
public void doValidate(Map<String, Object> context) {...}
}
HasExecutedValidate:责任链节点,校验是否已经执行
@Component
@ChainNode(chain = ChainConstant.DESIGN_VALIDATE_CHAIN, name = ChainConstant.HAS_EXECUTED_VALIDATE, index = -1)
public class HasExecutedValidate implements Validate<Map<String, Object>> {
@Override
public void doValidate(Map<String, Object> context) {...}
}
ValidateChainExecutor:责任链执行器
public class ValidateChainExecutor{
private Map<String, List<Validate>> chains = Maps.newHashMap();
private Map<String, Object> validations;
public ValidateChainExecutor(Map<String, Object> validations) {
this.validations = validations;
init();
}
/**
* 初始化责任链
*
* @author yuyouyang
* @date 2021/6/3 21:36
* @version 1.0
*/
private void init() {
final Class<ChainNode> validateAnnoClass = ChainNode.class;
validations.values()
.forEach(validation -> {
final ChainNode anno = validation.getClass()
.getAnnotation(validateAnnoClass);
chains.computeIfAbsent(anno.chain(), v -> new ArrayList<>())
.add((Validate) validation);
});
// 排序
chains.values()
.forEach(chain -> chain.sort(Comparator.comparingInt(c -> c.getClass()
.getAnnotation(validateAnnoClass)
.index())));
}
@SuppressWarnings("unchecked")
public <T> void execute(String chain, T context) {
chains.get(chain)
.forEach(validation -> validation.doValidate(context));
}
}
- 组装责任链
- 提供执行责任链的方法
ChainConfig:注册责任链
@Configuration
public class ChainConfig {
@Autowired
private ApplicationContext applicationContext;
@Bean
@ConditionalOnMissingBean
public ValidateChainExecutor getChainExecutor() {
return new ValidateChainExecutor(applicationContext.getBeansWithAnnotation(ChainNode.class));
}
}
- 注册为bean,使用时注入即可