前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >行为型设计模式:责任链模式以及mybatis中的责任链

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

作者头像
jinjunzhu
发布2020-08-20 15:40:12
4190
发布2020-08-20 15:40:12
举报
文章被收录于专栏:个人开发个人开发

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

上面就是一个非常简单的职责链模式的实现。这个实现的使用有很多场景,比如我们对一篇文章进行敏感词过滤,过滤内容包括政治敏感、涉黄等词汇,我们可以写几个过滤器分别过滤掉敏感词。

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<Interceptor> 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<Interceptor> 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;
  }
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 jinjunzhu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档