前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >责任链设计模式讲解

责任链设计模式讲解

作者头像
码农小胖哥
发布2019-12-10 16:22:31
4810
发布2019-12-10 16:22:31
举报
文章被收录于专栏:码农小胖哥的码农生涯
  前言  

很多框架如mybatis,servlet的filter,dubbo,安全框架诸如Spring security、apache shiro都会用到设计模式中的责任链模式,所以学习责任链模式成为帮助你学习以上这些框架的一个好的手段之一。今天我们就来了解一下责任链模式。

  定义  

如果有多个对象(Handler)都有机会处理数据源(RequestSource,这里不是单纯的数据库数据源,可以是一个请求,总之是来源),责任链可以使数据的发送者和接收者解耦,数据沿着责任链传递,直到有一个对象处理了它为止。形成了一条流水线的链条,所以称之为责任链,但是不仅仅局限于链条,还可以成树形或者环形,这取决于你的业务设计。

  场景  

插件设计、拦截器、过滤器等一些针对切入点的特定链式处理。都可以使用责任链模式。

实现方式

实现方式常用有两种,它们的不同主要是定义处理链的顺序和结构的不同,接下来我们来看看这两种方式。

 方式一 

通过处理器集合来定义处理顺序。好处在于可以集中管理处理器,指责单一。非常容易理解,容易实现。缺点是如果新增处理器(Handler)势必影响已有的处理器,只能顺序执行。处理流程是这样的:

接下来用代码来实现一下此模式:

HandlerChain 负责维护调用链条的顺序,这里默认实现用List来管理Handler

代码语言:javascript
复制
public interface HandlerChain {

    /**
     * 调用handler 处理 source.
     *
     * @param requestSource the request source
     */

    void doChain(RequestSource requestSource);
}



// 实现

public class DefaultHandlerChain implements HandlerChain {

    // 当前handler指针的位置
    private int pos = 0;
    private List<Handler> handlers = new ArrayList<>();

    public void addHandler(Handler handler) {
        handlers.add(handler);
    }


    @Override

    public void doChain(RequestSource requestSource) {
        int size = handlers.size();
        if (pos < size) {
          //注意对pos的处理
            Handler handler = handlers.get(pos++);
            handler.doHandler(requestSource, this);
        }
    }
}

Handler是处理链的节点抽象,是数据源(RequestSource)的具体处理者,它负责对数据的处理以及决定是否进入下一个Handler。

代码语言:javascript
复制
public interface Handler {

    /**
     * Do handler.
     *
     * @param requestSource 数据源
     * @param handlerChain 传入当前的Chain进行类似递归式的调用。
     */

    void doHandler(RequestSource requestSource,HandlerChain handlerChain);

}



// 其中一个实现

public class HeaderHandler implements Handler {
    @Override
    public void doHandler(RequestSource requestSource, HandlerChain handlerChain) {

       // 处理数据
        Integer header = requestSource.getHeader();
        System.out.println("header handler= " + header);
       //继续下一个 你可以根据条件来决定是否继续进行chain
        handlerChain.doChain(requestSource);
    }
}

 方式二 

该方式利用链表的指针特性。这里利用了链表的一部分特点,通过在当前的Handler指定下一个Handler来作为指针,相比较上面而言,Handler更自治,在节点的处理上更加灵活。

Handler负责指针以及逻辑处理:

代码语言:javascript
复制
public interface Handler {

    /**

     * 指针指向下一个处理节点.
     *
     * @return the next
     */

    Handler getNext();


    /**
     * 处理具体逻辑.
     *
     * @param requestSource the request source
    */

    void doHandler(RequestSource requestSource);

}



// 实现

public class HeaderHandler implements Handler {

    private Handler next;

    public HeaderHandler(Handler next) {
        this.next = next;
    }

    @Override
    public Handler getNext() {
        return next;
    }

    @Override
    public void doHandler(RequestSource requestSource) {

        Integer header = requestSource.getHeader();
        System.out.println("header = " + header);
        if (next != null) {
            next.doHandler(requestSource);
        }
    }
}

  总结  

责任链模式在各种常见框架中非常常见。所以建议各位在对此设计模式进行认真学习。 

demo地址:https://gitee.com/felord/chain-pattern.git

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农小胖哥 微信公众号,前往查看

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

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

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