• 设计模式:责任链模式


    责任链模式  


    一、 引言 
        初看责任链模式,心里不禁想起了一个以前听过的相声:看牙。说一个病人看牙的时候, 
    医生不小心把拔下的一个牙掉进了病人嗓子里。各个科室的医生推卸责任,搞得病人因此楼 
    上楼下的跑了不少冤枉路,最后无果而终。 
        责任链模式就是这种“推卸”责任的模式,你的问题在我这里能解决我就解决,不行就把 
    你推给另一个对象。至于到底谁解决了这个问题了呢?我管呢! 


    二、 定义与结构 
        从名字上大概也能猜出这个模式的大概模样——系统中将会存在多个有类似处理能力 
    的对象。当一个请求触发后,请求将在这些对象组成的链条中传递,直到找到最合适的“责 
    任”对象,并进行处理。 
         《设计模式》中给它的定义如下:使多个对象都有机会处理请求,从而避免请求的发送 
    者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一 
    个对象处理它为止。 
        呵呵,从定义上可以看出,责任链模式的提出是为了“解耦”,以应变系统需求的变更和 
    不明确性。 
        下面是《设计模式》中给出的适用范围: 
    1)  有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。 
    2)  你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 
    3)  可处理一个请求的对象集合应被动态指定。 


        责任链模式真的能给发送者和接收者之间解耦(这好像很神奇)吗?先来看下它的组成 
    角色。这个问题我会在下面提及。 
        责任链模式由两个角色组成: 
    1)  抽象处理者角色(Handler):它定义了一个处理请求的接口。当然对于链子的不同实现, 
        也可以在这个角色中实现后继链。 
    2)  具体处理者角色(Concrete   Handler):实现抽象角色中定义的接口,并处理它所负责 
        的请求。如果不能处理则访问它的后继者。 
        至于类图不放也罢。毕竟就是一个继承或者实现。 


    三、 纯与不纯 
        责任链模式的纯与不纯的区别,就像黑猫、白猫的区别一样。不要刻意的去使自己的代 
    码来符合一个模式的公式。只要能够使代码降低耦合、提高重用,满足系统需求并能很好的 
    适应变化就好了。正所谓:管它黑猫白猫,抓住老鼠就是好猫! 
        纯的责任链模式,规定一个具体处理者角色只能对请求作出两种动作:自己处理;传给 
    下家。不能出现处理了一部分,把剩下的传给了下家的情况。而且请求在责任链中必须被处 
    理,而不能出现无果而终的结局。 
        反之,则就是不纯的责任链模式。 
        不纯的责任链模式还算是责任链模式吗?比如一个请求被捕获后,每个具体处理者都尝 
    试去处理它,不管结果如何都将请求再次转发。我认为这种方式的实现,算不算是责任链模 
    式的一种倒不重要,重要的是我们也能从中体味到责任链模式的思想:通过将多个处理者之 
    间建立联系,来达到请求与具体的某个处理者的解耦。 
        下面的例子就是采用了上面提到的“不纯的责任链模式”。 


    四、 举例 
        这个例子来源于项目中我刚刚完成的一个小功能点——“代号自动生成器”。在项目中存 
    在很多地方,比如:员工工号、档案代号,要求客户在使用时输入。而这些代号对于一个特 
    定的企业或者类别,往往有一定的规则。因此可以让用户在系统参数中维护一定的规则,然 
    后通过“代号自动生成器”来给用户生成代号。 
        根据初期需求,用户代号中往往存在以下几种变动元素:年份、月份、日期、流水号。 
    由于需求比较简单,因此考虑到用户可能存在其他变动元素,所以我打算在“被第一颗子弹 
    击中”后重构一下现有的结构。下面就是我在头脑中演绎过的使用责任链模式的重构。 
        这里只用来说明下责任链模式的结构和使用,因此不体现功能细节。 


        //这是抽象处理者角色 


        public interface CodeAutoParse { 


          //这里就是统一的处理请求使用的接口 


           String[] generateCode(String moduleCode, int number, String rule,String[] target) 
                throws BaseException; 
        } 


        //这个为处理日期使用的具体处理者 


        public class DateAutoParse implements CodeAutoParse{ 
           //获取当前时间 


           private final Calendar currentDate = Calendar.getInstance(); 


             //这里用来注入下一个处理者,系统中采用Spring Bean 管理 


             private CodeAutoParse theNextParseOfDate; 


             public void setTheNextParseOfDate(CodeAutoParse theNextParseOfDate){ 
            this.theNextParseOfDate = theNextParseOfDate ; 
           } 


           /* 
            *实现的处理请求的接口 
           *这个接口首先判断用户定义的格式是否有流水号,有则解析,没有则跳过 
           *下传到下一个处理者 


          */ 
           public String[] generateCode(String moduleCode, int number, String rule, String[] 
        target) 
                throws BaseException { 
                //这里省略了处理的业务 


                …… 
                if(theNextParseOfDate != null) 

                    return theNextParseOfDate.generateCode(moduleCode , number , rule, 
    target) 
                else 
                    return target; 
        } 


        其它具体处理者也是如此的结构,每一个里面都设置有一个用来存放下一个处理者的引 
    用,不管你有没有下一个处理者。 
        其实责任链模式本身的结构和使用都没有什么,就是一个继承或者实现。在处理请求的 
    时候,按照规定去调用下一个处理者。但是怎么来维护这样一条链子呢? 
         《设计模式》一书中仅仅说必须自己引入它,可以参考使用list 或者 map 来进行注册。 
    而在上面我使用spring 来管理具体处理者角色的引入。当有了新的处理者需要添加的时候, 
    仅仅需要修改下配置文件。 


    五、 其他 
        责任链模式优点,上面已经体现出来了。无非就是降低了耦合、提高了灵活性。但是责 

    任链模式可能会带来一些额外的性能损耗,因为它每次执行请求都要从链子开头开始遍历。 

    下载:

    http://download.csdn.net/detail/undoner/5335717

    深入浅出设计模式-中文版



    1.简述职责链的优缺点;

    优点如下:

    1)降低耦合度

    在职责链模式里面,请求者并不知道接收者是谁,也不知道具体如何处理,请求者只是负责向职责链发出请求就可以了。而每个职责对象也不用管请求者或者是其它的职责对象,只负责处理自己的部分,其它的就交由其它的职责对象去处理。也就是说,请求者和接收者是完全解耦的。 

    2)可简化对象的相互连接

    3)增强给对象指派职责的灵活性

    职责链模式会把功能处理分散到单独的职责对象里面,然后在使用的时候,可以动态组合职责形成职责链,从而可以灵活的给对象分配职责,也可以灵活的实现和改变对象的职责。

    (4)增加新的请求处理类很方便

    缺点如下:

    1)不能保证请求一定被接收

    职责链模式的每个职责对象只负责自己处理的那一部分,因此可能会出现某个请求,把整个链传递完了,都没有职责对象处理它。这就需要在使用职责链模式的时候注意,需要提供默认的处理,并且注意构建的链的有效性。 

    2)系统性能将受到一定影响,而且在进行代码调试时不太方便;可能会造成循环调用

    2.简述职责链模式的使用范围

    有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

    在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

    可动态指定一组对象处理请求。

    3. 简要分析职责链的本质

    1)分离职责 

    分离职责是前提,只有先把复杂功能分开,拆分成很多的步骤和小的功能处理,然后才能合理规划和定义职责类,可以有很多的职责类来负责处理某一个功能,让每个职责类负责处理功能的某一个方面,在运行期间进行动态组合,形成一个处理的链,把这个链运行完,那么功能也就处理完了

    2)动态组合才是职责链模式的精华所在,因为要实现请求对象和处理对象的解耦,请求对象不知道谁才是真正的处理对象,因此要动态的把可能的处理对象组合起来,由于组合的方式是动态的,这就意味着可以很方便的修改和添加新的处理对象,从而让系统更加灵活和具有更好的扩展性。

        这么做还会有一个潜在的优点,就是可以增强职责功能的复用性。如果职责功能是很多地方都可以使用的公共功能,那么它可以应用在多个职责链中复用。



  • 相关阅读:
    Visio2019专业版激活方法
    I2C总线协议
    latch-up和Antenna-effect
    读--数字集成电路物理设计
    数字IC设计流程与工具
    读--FPGA设计指导原则
    读--数字集成电路设计与实现
    FIFO
    半导体存储器
    触发器
  • 原文地址:https://www.cnblogs.com/wuyida/p/6301016.html
Copyright © 2020-2023  润新知