`
xyheqhd888
  • 浏览: 409209 次
  • 性别: Icon_minigender_1
  • 来自: 秦皇岛
社区版块
存档分类
最新评论

责任链(Chain of Responsibility)模式

阅读更多

 

   面向对象开发人员通常希望明确和减少对象间的责任,从而降低对象之间的耦合程序.这样我们的系统更加容易修改,同时也可降低产生缺陷的风险。从某种程序上说,Java语言本身能够帮助降低对象间的耦合度。客户端只能访问对象的可见接口,而无需关心对象的实现细节。借助于这种组织方式,客户端代码只需了解哪些类有哪些方法可调用即可;除此之外,客户端代码与被使用的代码无任何关联。如果我们将若干对象按照某种层次结构进行组织,比如组织为类责任链,客户端代码就有可能不必事先了解自己将使用哪一个类。在这种情况下,链中的每个对象都有一个方法,当客户端代码调用该方法的时候,这些对象要么执行该方法,要么沿着这条链转发该方法调用请求。

 

   Chain of Responsibility模式可让每个对象都有一次机会决定自己是否处理请求,以便于避免请求的发送者与其接收者之间的耦合

 

1.常见的责任链:

   正如组合模式中介绍的那样,Oozinoz把机器、生产线、车间、工厂模型化为“机器组件”。通过这种方法,操作可以简单地并以递归方式实现,比如关闭某车间中所有机器的操作,也可以简化对工厂中工程师职责的模拟。在Oozinoz公司中,始终有位工程师负责某个特定的机器组件,尽管这种职责也许是按照层次分配的。比如对于火药球填压机这样一台复杂的机器,也许会直接分配一个责任工程师。对于简单的机器,也许不会直接分配责任工程师,负责本机器所在生产线或者所在车间的工程师同时对这台机器负责。

   我们希望当客户对象查询责任工程师时,能够避免查询多个对象。为完成这个使命,我们可以使用Chain of Responsibility模式,分配给每个机器组件一个责任人对象。下图可以说明这种设计思路:


                                      

     每个Machine或者MachineComposite对象都有父对象(parent)

       和责任人对象(responsible),这些属性是从MachineComponent类继承的

 

    上图的设计思路允许(但不是强制要求)每个机器组件跟踪其责任工程师。如果某机器没有直接分配责任工程师,它可以把查询责任工程师的请求发送给其父类。一般来讲,机器的父类是生产线,生产线的父类是车间,车间的父类是工厂。在Oozinoz公司中,这个职责链始终有一位责任工程师。

    这种设计思路和好处是机器组件的客户代码不必了解责任工程师是如何分配的。客户代码可以询问任何机器组件或者其责任工程师。机器组件把客户代码与职责分配知识相互独立起来。当然在另一方面,这种设计思路也存在不合适的地方。

 

突破题:请指出上图中设计思路的两个明显弱点。

答:此设计思路(目的是查找机器的责任工程师)的一些潜在缺陷陈列如下:

(1) 我们没有指定责任链如何设置以便于机器知道其父对象。实际上,很难保证父对象始终不是null。

(2) 根据父对象设置方式,搜索父对象有可能陷入死循环,这一点是可以想象的。

(3) 并不是怕有对象都拥有这些新方法暗示的所有行为(比如顶层没有父项)。

(4) 当前设计局限于细节,关心系统如何知道哪些工程师在工厂,以及是否可用。该设计并不清楚完成责任需要的实际时间。

 

   Chain of Responsibility模式可以帮助我们简化客户端代码,尤其当客户端代码不清楚对象组中哪个对象负责处理查询请求时。如果事先没有建立Chain of Responsibility模式,代码会比较复杂,也许要借助其他方法来简化代码设计。

 

2.重构为Chain of Responsibility模式:

  如果发现客户端代码在发出调用请求之前首先进行调用探查时,也许就应该通过代码重构来改善代码设计了.为了决定是否使用Chain of Responsibility模式,需要事先明确类组中对象是否支持责任链。比如Oozinoz的机器组件有时提供对责任工程师的引用。把期望的操作添加到类组中的每个类,并用链策略来实现这个操作能够满足这个请求。

  下面让我们考虑Oozinoz代码库中对工具和工具车的建模。工具不属于MachineComponent类层次,但是在某些地方与机器类似。尤其是工具始终分配给工具图形,并且工具车有一个责任工程师这些方面。假设某可视化程序可以显示特定车间的所有工具和机器,并且提供弹出式信息以显示特定项的责任工程师。下图显示了在查询指定设备的责任工程师的过程中所涉及的类:



        某模拟环境下包含的设备项,包括各种机器、机器组合、工具以及工具车

   VisualizationItem接口指定类需要的部分行为,以便于实现可视化,同时不需要getResponsible()方法。实际上,并不是VisualizationItem的所有项都知道具体的责任工程师。当可视化程序需要决定哪个工程师对特定设备负责时,答案依赖于所选的是哪个设备项。机器、机器组和工具车都有getResponsible()方法,但是工具没有。为确定工具的责任工程师,程序代码必须查看这个工具属于哪个工具车,然后查看谁负责这个工具车。为确定指定设备项的责任工程师,应用程序的菜单代码使用一些if语句和类型判断。这些特性表明重构也许有助于改善代码,具体代码如下:

package ocm.oozinoz.machine;

public class AmbitiousMenu
{
          public Engineer getResponsible(VisualizationItem item)
          {
                if ( item instance of Tool)
                {
                       Tool t = (Tool)item;
                       return t.getToolCard().getResponsible();
                }

                 if ( item instance of ToolCart)
                {
                       ToolCart tc = (ToolCart)item;
                       return tc.getResponsible();
                }

                if ( item instance of MachineComponent)
                {
                       MachineComponent c = (MachineComponent)item;
                       if(c.getReponsible()!=null)
                         return c.getResponsible();
                       if(c.getParent() != null)
                         return c.getParent().getReponsible(); 
                }
                 return null;
          }
}

Chain of Responsibility模式的目的是减轻调用者的压力,使它们无需了解哪个对象可以处理调用请求。在本例中,调用者是个菜单,其请求是找到责任工程师。在当前设计中,调用者必须了解哪个设备项有getReponsible()方法。借助于Chain of Reponsiblity模式为所有模拟项提供责任人,我们可以借此来简化代码。这样菜单代码就不必了解哪些对象了解责任工程师相关的知识,而可以迁移到模拟项中。

 

突破题:我们可以将getReponsible()方法移入VisualizationItem接口,并将该方法加入Tool类。请据此重新绘制上面的类图。


                           

                                         每个VisualizationItem对象知道其责任工程师。从内部实现来讲,

                                                VisualizationItem对象也许把这个请求转发给其父对象

   通过这样的设计,客户代码可以借助责任链上的任何模拟对象来获取相关责任工程师的信息。另外,这个方法让客户不必掌握哪些对象知道职责,可以把负担全部转移给实现VisualizationItem接口的对象。

   现在,菜单代码可以直接通过调用VisualizationItem对象的方法来查找责任工程师,代码将会更简单:

package com.oozinoz.machine;

public class AmbitiousMenu2
{
     public Engineer getResponsible(VisualizationItem item)
     {
          return item.getResponsible();
     }
}

每个设备项的getResponsible()方法也会变得更加容易实现。

 

突破题:请给出下面的类的getResponsible()方法的实现:

A.MachineComponent

B.Tool

C.ToolCart

 

答:A.一个MachineComponent对象可能对应一名责任人。如果某个MachineComponent对象并不对应一名责任人,该对象将会把对getResponsible()方法的调用转发给其父类节点对象:

 

public Engineer getResponsible()
{
    if(responsible != null) 
       return responsible;
    if(parent != null)
       return parent.getReponsible();
    return null;
}

 

B.Tool.Responsible类根据“工具总是被指派给某个工具车”这样一个原则来实现getResponsible()方法:

public Engineer getResponsible()
{
    return toolCart.getResponsible();
}

C.ToolCart类根据“每个工具车都有一名责任工程师”这样一个原则来实现getResponsible()方法:

public Engineer getResponsible()
{
    return responsible;
}

 

3. 固定责任链

  当我们在为MachineComponent类编写getResponsible()方法的时候,必须考虑到MachineComponent对象的父对象可能为空。解决方法之一是,让每个MachineComponent对象都有一个非空对象。这样做可以让我们的对象模型更加紧凑。为实现这个目的,可以为MachineComponent类的构造器增加一个参数来提供父对象(如果所提供的父对象为空,甚至可以抛出一个异常,以便知道异常被捕获的位置)。另外,我们要考虑到位于根部的对象---该对象没有父对象。一种可行的做法是,创建一个MachineRoot类,并让该类继承MachineComposite类(而不是MachineComponent)。为了保证每个MachineComponent对象都对应一名责任工程师,可以这样做:

 (1)MachineRoot类的构造器需要一个Enginner对象;

 (2)MachineComponent类的构造器需要一个类型为MachineComponent的父对象;

 (3)只有MachineRoot使用null作为其父对象的值。

 

突破题:请在下图中写出各个类的构造器,从而保证每个MachineComponent对象都对应一名责任工程师。



     MachineComponent类层次结构的构造器支持两个准则:MachineRoot对象必须有一个责任工程师对象;除了根对象以外的每个MachineComponent对象都必须有一个父节点

 

我们为Machine类和MachineComposite类提供的构造器,应该保证无论是否配备有责任工程师,两个类都能被初始化。如果某个MachineComponent对象没有指派一名责任工程师,那么就从其父节点对象那里获取责任工程师。 

 

  通过固定责任链,我们的对象模型变得更加健壮,其代码也愈加简化。现在就可以把MachineComponent类的getResponsible()方法实现如下:

public Engineer getResponsible()
{
    if(responsible!=null)
      return responsible;
    return parent.getResponsible();
}

 

12.4 不带组合结构的Chain of Responsibility模式 

    在使用Chain of Responsiblity模式的时候,我们需要确定一个查询策略来指定查找处理请求对象的查询顺序。通常,采用哪种查询策略取决于建模领域的背景知识。如果对象模型中存在某些类型的组合,如Oozinoz公司的机器类层次结构,那么就会经常出现这种情况。不过Chain of Responsibility模式也可以用于不带组合结构的对象模型中。

 

突破题:请举出一个例子,说明Chinn of Responsibility模式可应用于不带组合结构的对象链模型中。

答:(1)一群接线工程师按照标准的循环顺序轮流为客户服务。这些接线工程师形成了一个环状的链。如果当前首席工程师在一定的时间内回答不了有关产品支持的问题,通知系统则将切换到下一位工程师,请他来回答这个问题。

     (2)当用户在输入事件日期等信息的时候,一些解析器会轮渡来解析用户输入的文本,这些解析器也形成一个链。

 

5.小结

  当应用Chain of Responsibility模式后,客户端代码不必事先知道对象集合中哪个对象可提供自己所需要的服务。当客户端代码发出调用请求之后,该请求沿着责任链转发,直到找到提供该服务的对象为止。这样可大大降低客户端代码与提供服务的对象之间的耦合程度。

  如果某个对象链能够应用一系列不同的策略来解决某个问题,如解析用户的输入,那么这种情况也可以应用Chain of Responsibility模式。该模式更常见于组合结构;该结构具有一个包容的层次结构,它为对象链提供一种自然的查询顺序。简化对象链和客户端的代码是Chain of Responsibility模式的一个主要优点。

  • 大小: 3.6 KB
  • 大小: 5.9 KB
  • 大小: 5.4 KB
  • 大小: 8.1 KB
分享到:
评论

相关推荐

    Chain of Responsibility模式

    **Chain of Responsibility模式详解** Chain of Responsibility模式是GOF(GoF,Gang of Four)在他们的经典著作《设计模式:可复用面向对象软件的基础》中提出的23种设计模式之一,属于行为模式类别。这个模式的...

    【Java设计模式】(3)责任链Chain of Responsibility

    **Java设计模式——责任链(Chain of Responsibility)** 在软件工程中,设计模式是一种解决常见问题的可重用解决方案。责任链模式是行为设计模式之一,它的主要思想是将请求的发送者和接收者解耦,通过将多个处理...

    设计模式C++学习之责任链模式(Chain of Responsibility)

    责任链模式(Chain of Responsibility)是一种行为设计模式,它允许将请求沿着处理者对象的链进行传递,直到某个对象能够处理这个请求。这种模式的主要优点是解耦了发送者和接收者之间的关系,使得系统更加灵活,...

    Chain Of Responsibility模式

    Chain of Responsibility(责任链)模式是一种行为设计模式,它允许将请求沿着处理者对象的链进行发送,每个对象都可以处理请求或将其传递给链中的下一个对象。这种模式常用于事件处理或者命令的执行流程,使得多个...

    c++-设计模式之责任链模式(Chain of Responsibility Pattern)

    责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许将请求的发送者和接收者解耦。通过将请求沿着处理链传递,直到有对象处理该请求为止,这种模式避免了请求发送者与具体处理者之间的紧...

    Chain of Responsibility 职责链模式

    C#面向对象设计模式 Chain of Responsibility 职责链模式 视频讲座下载

    java设计模式之责任链(chain of responsibility)

    责任链(Chain of Responsibility)模式是一种行为设计模式,它允许我们向对象链中传递请求,让每个对象决定是否处理这个请求。在Java中,这种模式常用于事件处理、日志系统或者权限控制等场景,其核心思想是将处理...

    (行为型模式) Chain Of Responsibility 职责链模式

    C#面向对象设计模式 (行为型模式) Chain Of Responsibility 职责链模式 视频讲座下载

    chain of responsibility.pptx

    责任链模式(Chain of Responsibility Pattern)是一种常见的行为模式。 使多个对象都有处理请求的机会,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象串成一条链,并沿着这条链一直传递该请求,直到有...

    chain of responsibility 职责链模式(行为模式)

    职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求的发送者和接收者解耦,使得多个对象都有可能处理一个请求,而无需显式指定接收者。在这个模式中,请求沿着一个处理者链进行传递,...

    设计模式 - Chain of Responsibility Pattern(责任链模式)

    NULL 博文链接:https://linkcqu.iteye.com/blog/355806

    chain-of-responsibility-demo 责任链模式demo

    在这个`chain-of-responsibility-demo`中,我们可以预期找到一个实际应用了责任链模式的代码示例。通常,它会包含以下关键组件: 1. **Handler**(处理器):这是责任链中的基本单元,每个处理器都实现了处理请求的...

    Java设计模式之责任链模式(Chain of Responsibility模式)介绍

    责任链模式(Chain of Responsibility,CoR)是一种行为设计模式,它允许将请求沿着处理者对象的链式结构进行传递,直到某个对象处理这个请求。每个处理者对象都包含对下一个处理者的引用,如果当前处理者无法处理...

    C#面向对象设计模式纵横谈(20):(行为型模式) Chain Of Responsibility 职责链模式

    职责链模式(Chain of Responsibility)是一种行为型设计模式,它允许将请求沿着处理者对象的链进行传递,直到某个对象能够处理这个请求。在C#中,职责链模式的应用可以帮助我们构建灵活、可扩展的系统,减少对象...

    C#面向对象设计模式纵横谈(14):Chain of Responsibility 职责链模式(行为型模式) (Level 300)

    职责链模式(Chain of Responsibility)是一种行为型设计模式,它允许你将请求沿着处理者对象的链进行传递,直到某个对象处理该请求。在C#编程中,职责链模式能够帮助我们实现一种松耦合的架构,使得请求的发送者和...

    C#面向对象设计模式纵横谈(14):Chain of Responsibility 职责链模式(行为型模式)

    ### C#面向对象设计模式纵横谈(14):Chain of Responsibility 职责链模式(行为型模式) #### 概述 在本篇文章中,我们将深入探讨C#中的Chain of Responsibility(职责链)模式,这是行为型设计模式的一种。虽然标题...

    JAVA设计模式之行为模式 责任链模式和状态模式

    本篇将探讨两种重要的行为设计模式:责任链模式(Chain of Responsibility Pattern)和状态模式(State Pattern)。 **责任链模式**是一种使多个对象都有机会处理请求的模式,避免请求发送者与接收者之间的耦合。在...

    责任链模式_javaDemo

    责任链模式(Chain of Responsibility)的目标是使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。 在处理用户的...

    04-Chain Of Responsibility.rar

    《责任链模式:构建灵活的处理流程》 责任链模式是一种行为设计模式,它允许将请求沿着处理者链进行发送,每个处理者都可以选择处理请求或将其传递给链中的下一个处理者。这种模式使得系统可以灵活地添加、删除或...

Global site tag (gtag.js) - Google Analytics