职责链模式定义是把一个请求传递给多个对象来处理,这些对象都放在一条链上,以实现发送和接受解耦。GoF的《设计模式》中英文定义如下:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
1.下面看一种最简单的职责链模式。先定义一个处理接口
public interface Handler {
void handle(String event);
}
然后定义2个处理实现类
public class HandlerA implements Handler{
@Override
public void handle(String event) {
System.out.println("handler A handle, event:" + event);
}
}
public class HandlerB implements Handler{
@Override
public void handle(String event) {
System.out.println("handler B handle, event:" + event);
}
}
定义职责链类
public class HandlerChain {
private List handlers = new ArrayList<>(5);
public void addHandler(Handler handler){
handlers.add(handler);
}
public void handle(String event){
handlers.forEach(r -> r.handle(event));
}
}
再加上一个测试类:
public class TestChain {
public static void main(String[] args){
HandlerChain handlerChain = new HandlerChain();
handlerChain.addHandler(new HandlerA());
handlerChain.addHandler(new HandlerB());
handlerChain.handle("test event");
}
}
上面就是一个非常简单的职责链模式的实现。这个实现的使用有很多场景,比如我们对一篇文章进行敏感词过滤,过滤内容包括政治敏感、涉黄等词汇,我们可以写几个过滤器分别过滤掉敏感词。
2.上面的职责链模式实现非常简单,但是它更适用于所有的处理类都进行处理的场景。但是如果现在有一种场景,职责链中只要有一个处理类处理成功就不再继续往下传,该怎么实现呢?这种情况就需要对Handler做一些控制,用一个抽象类来封装next指针和对next指针的调用,看如下代码:
public interface Handler1 {
void handle(String event);
void setNext(Handler1 handler);
}
public abstract class AbstractHandler1 implements Handler1{
public Handler1 next;
@Override
public void setNext(Handler1 handler){
this.next = handler;
}
@Override
public void handle(String event) {
boolean result = doHandle(event);
if(!result && hasNext()){
next.handle(event);
}
}
protected boolean hasNext(){
return this.next != null;
}
public abstract boolean doHandle(String event);
}
public class HandlerC extends AbstractHandler1{
@Override
public boolean doHandle(String event) {
System.out.println("handler C handle, event:" + event);
return false;
}
}
public class HandlerD extends AbstractHandler1{
@Override
public boolean doHandle(String event) {
System.out.println("handler D handle, event:" + event);
return false;
}
}
再看测试类,
public class TestChain {
public static void main(String[] args){
HandlerChain1 handlerChain1 = new HandlerChain1();
handlerChain1.handle();
}
}
3.mybatis中的责任链
mybatis中的责任链使用了注解的方式来识别handler类,内部并没有实现,只是预留出接口。
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
注解接口如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Intercepts {
Signature[] value();
}
责任链类:
public class InterceptorChain {
private final List interceptors = new ArrayList<>();
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
public void addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
}
public List getInterceptors() {
return Collections.unmodifiableList(interceptors);
}
}
在实例化Executor、ParameterHandler、ResultSetHandler、StatementHandler这4个对象时,把这4个对象植入到责任链中,然后用处理类对这些对象做一些操作。
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
}
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
public Executor newExecutor(Transaction transaction) {
return newExecutor(transaction, defaultExecutorType);
}
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
源码地址:https://github.com/jinjunzhu/design-pattern.git
欢迎关注个人公众号,共同学习进步