美文网首页
责任链Chain Of Responsibility

责任链Chain Of Responsibility

作者: 朱万宇 | 来源:发表于2018-04-23 12:17 被阅读0次

    前言

    写方法的原则要尽量做到一个方法只做一件事情, 这样做到职责单一, 日后对于代码的维护也非常容易。 并且代码的复用性也会很高。

    在某些情况下, 对于某个事件或某个消息的处理是一个接一个的, 而又不想以下这种写法

    process(Message a){
        b = doSomethingA(a)
        c = doSomethingB(b)
        d = doSomethingC(c)
        e = doSomethingD(d)
    }
    

    以上这种写法很容易, 可以明显看到执行的顺序,也可以保证一个方法只做一件事情, 让后将这些事情连起来。

    一些弊端

    1. 代码不易维护
      假如在第二步中我们想改为多线程执行, 则需要改动process中的代码, 而针对职责链则仅需加入多线程节点来使得后续的处理变为多线程。

    2. 调用关系的臃肿
      我们能看到, 上面代码的调用是process作为调用方, 连续调用a,b,c,d方法, process未必仅仅是调用a,b,c,d 。在程序种往往要进行逻辑判断, 比如如果B方法的的返回值c为null, 则不再向后执行,那么我们可能会在process方法种在后面加上该判断

        if(c == null){
            return; 
        }
    

    如果是更复杂的逻辑处理, 异常处理等, 就需要在process方法种加入相应的逻辑处理代码, 从而使得代码变得越来越臃肿。

    换一种思路

    这时候我们想, 能否使得上一次的调用对下一次的调用负责, 而不是通过process这层来管理, 如下图显示

    职责链简图

    那么像这样的如链式调用的机构, 就叫做职责链。

    其实在java中,已经有很多地方遇到过它。

    我们在哪里见过职责链这种模式

    1. java web filter
      在java web开发中, 最早的应该就属filter了
      实现Filter接口, 重写doFilter.
        public void doFilter(ServletRequest req, ServletResponse resp,
                FilterChain chian) throws IOException, ServletException {
            chian.doFilter(...)
        }
    

    如果接触过socket编程, 对mina 或者netty框架熟悉的话, 责任链模式将更不陌生。
    在mina中:
    通过FilterChianBuilder, FilterChain, IoFilter 构成一个链。 创建方式如下

    DefaultIoFilterChainBuilder builder = new DefaultIoFilterChainBuilder();
    builder.addFirst("mdcInjectionFilter", new MdcInjectionFilter(MdcInjectionFilter.MdcKey.remoteAddress));
    builder.addAfter("mdcInjectionFilter", "codExecutorFilter", new ExecutorFilter());
    builder.addAfter("codExecutorFilter", "loggingFilter", new LoggingFilter());
    builder.addAfter("loggingFilter", "codecFilter", codecFilter);
    builder.addAfter("codecFilter", "executorFilter", executorFilter);
    builder.addAfter("executorFilter", "writeExecutorFilter", new ExecutorFilter(IoEventType.WRITE));
    DefaultIoFilterChain chain = new DefaultIoFilterChain();
    builder.buildFilterChain(chain);
    
    

    这样就构造了一条职责链, 每一个节点负责下面一个节点, 节点内执行一定的逻辑。 至于如何构造职责链可以看我的mina源码分析

    1. netty 中
      在netty中, 核心的业务逻辑有一系列ChannelHandler处理。
      netty中分为 inBound 和 outBound, 在channelpipeline 中, inbound 和outbound channelhandler 处理读和写。
      可以通过下面代码创建:
    ChannelPipeline pipeline = ch.pipeline();
    pipeline.addLast("handler1", firstHandler);  
    pipeline.addFirst("handler2", new SecondHandler());  
    pipeline.addLast("handler3", new ThirdHandler());  
    
    

    当然在netty还有其他几个重要成员Channel, ChannelHandlerContext, EventLoop, EventLoopGroup, 这些不在这里阐述, 有兴趣的话可以看《netty in action》。

    后话

    职责链模式能让模块结构更加清晰, 节点与节点之间的修改影响会非常小。 但是并不适合所有的场景, 要结合具体的场景分析。

    相关文章

      网友评论

          本文标题:责任链Chain Of Responsibility

          本文链接:https://www.haomeiwen.com/subject/ehmklftx.html