行为型设计模式:责任链模式以及mybatis中的责任链

       职责链模式定义是把一个请求传递给多个对象来处理,这些对象都放在一条链上,以实现发送和接受解耦。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

   欢迎关注个人公众号,共同学习进步

行为型设计模式:责任链模式以及mybatis中的责任链_第1张图片

 

你可能感兴趣的:(设计模式)