⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pat5a.htm

📁 设计模式英文版 作者:Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides 四人帮的书。 学设计模式的必读的书籍!经典中的经典
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML>

<HEAD><TITLE>Chain of Responsibility</TITLE></HEAD>

<BODY	BGCOLOR		= #FFFFFF
	TEXT		= #000000
>

<A NAME="top"></A>
<A NAME="intent"></A>
<H2><A HREF="#motivation"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Intent</H2> 

<A NAME="auto1000"></A>
<P>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.</P>

<A NAME="motivation"></A>
<H2><A HREF="#applicability"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Motivation</H2> 

<A NAME="auto1001"></A>
<P>Consider a context-sensitive help facility for a graphical user
interface.  The user can obtain help information on any part of the
interface just by clicking on it. The help that's provided depends on
the part of the interface that's selected and its context; for
example, a button widget in a dialog box might have different help
information than a similar button in the main window.  If no specific
help information exists for that part of the interface, then
the help system should display a more general help message about the
immediate context&#151;the dialog box as a whole, for example.</P>

<A NAME="auto1002"></A>
<P>Hence it's natural to organize help information according to its
generality&#151;from the most specific to the most general.  Furthermore,
it's clear that a help request is handled by one of several user
interface objects; which one depends on the context and how specific
the available help is.</P>

<A NAME="auto1003"></A>
<P>The problem here is that the object that ultimately <EM>provides</EM> the
help isn't known explicitly to the object (e.g., the button) that <EM>initiates</EM> the help request. What we need is a way to decouple the
button that initiates the help request from the objects that might
provide help information. The Chain of Responsibility pattern defines
how that happens.</P>

<A NAME="auto1004"></A>
<P>The idea of this pattern is to decouple senders and receivers by
giving multiple objects a chance to handle a request.  The request
gets passed along a chain of objects until one of them handles it.</P>

<A NAME="223o"></A>
<P ALIGN=CENTER><IMG SRC="Pictures/chain090.gif">

<A NAME="def-implicitreceiver"></A>
<P>The first object in the chain receives the request and either handles
it or forwards it to the next candidate on the chain, which does
likewise.  The object that made the request has no explicit knowledge
of who will handle it&#151;we say the request has an <STRONG>implicit
receiver</STRONG>.

<A NAME="auto1005"></A>
<P>Let's assume the user clicks for help on a button widget marked
"Print."  The button is contained in an instance of PrintDialog,
which knows the application object it belongs to (see preceding object diagram).
The following interaction diagram illustrates how the help
request gets forwarded along the chain:</P>

<A NAME="224ci"></A>
<A NAME="224i"></A>
<P ALIGN=CENTER><IMG SRC="Pictures/chain091.gif">

<A NAME="auto1006"></A>
<P>In this case, neither aPrintButton nor aPrintDialog handles the
request; it stops at anApplication, which can handle it or ignore it.
The client that issued the request has no direct reference to the
object that ultimately fulfills it.</P>

<A NAME="def-successor"></A>
<P>To forward the request along the chain, and to ensure receivers remain
implicit, each object on the chain shares a common interface for
handling requests and for accessing its <STRONG>successor</STRONG> on the
chain.  For example, the help system might define a HelpHandler class
with a corresponding HandleHelp operation. HelpHandler can be the
parent class for candidate object classes, or it can be defined as a
mixin class. Then classes that want to handle help requests can make
HelpHandler a parent:</P>

<A NAME="224c"></A>
<P ALIGN=CENTER><IMG SRC="Pictures/chain092.gif">

<A NAME="auto1007"></A>
<P>The Button, Dialog, and Application classes use HelpHandler operations
to handle help requests.  HelpHandler's HandleHelp operation forwards
the request to the successor by default.  Subclasses can override this
operation to provide help under the right circumstances; otherwise
they can use the default implementation to forward the request.</P>

<A NAME="applicability"></A>
<H2><A HREF="#structure"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Applicability</H2> 

<A NAME="auto1008"></A>
<P>Use Chain of Responsibility when</P>

<UL>

<A NAME="auto1009"></A>
<LI>more than one object may handle a request, and the handler isn't known
<EM>a priori</EM>.  The handler should be ascertained automatically.

<A NAME="auto1010"></A>
<P></P>

<A NAME="auto1011"></A>
<LI>you want to issue a request to one of several objects without
specifying the receiver explicitly.

<A NAME="auto1012"></A>
<P></P>

<A NAME="auto1013"></A>
<LI>the set of objects that can handle a request should be specified
dynamically.

</UL>

<A NAME="structure"></A>
<H2><A HREF="#participants"><IMG SRC="gifsb/down3.gif" BORDER=0></A>
Structure</H2> 

<P ALIGN=CENTER><IMG SRC="Pictures/chain094.gif">

<A NAME="auto1014"></A>
<P>A typical object structure might look like this:

<P ALIGN=CENTER><IMG SRC="Pictures/chain089.gif">

<A NAME="participants"></A>
<H2><A HREF="#collaborations"><IMG SRC="gifsb/down3.gif" BORDER=0></A>
Participants</H2>

<UL>

<A NAME="auto1015"></A>
<LI><B>Handler</B> (HelpHandler)

<A NAME="auto1016"></A>
<P></P>

<UL>

    <A NAME="auto1017"></A>
<LI>defines an interface for handling requests.

    <A NAME="auto1018"></A>
<P><!-- extra space --></P>

    <A NAME="auto1019"></A>
<LI>(optional) implements the successor link.

</UL>

<A NAME="auto1020"></A>
<P></P>

<A NAME="auto1021"></A>
<LI><B>ConcreteHandler</B> (PrintButton, PrintDialog)

<A NAME="auto1022"></A>
<P></P>

<UL>

    <A NAME="auto1023"></A>
<LI>handles requests it is responsible for.

    <A NAME="auto1024"></A>
<P><!-- extra space --></P>

    <A NAME="auto1025"></A>
<LI>can access its successor.

    <A NAME="auto1026"></A>
<P><!-- extra space --></P>

    <A NAME="auto1027"></A>
<LI>if the ConcreteHandler can handle the request, it does so;
    otherwise it forwards the request to its successor.

</UL>

<A NAME="auto1028"></A>
<P></P>

<A NAME="auto1029"></A>
<LI><B>Client</B>

<A NAME="auto1030"></A>
<P></P>

<UL>

    <A NAME="auto1031"></A>
<LI>initiates the request to a ConcreteHandler object on the chain.

</UL>

</UL>

<A NAME="collaborations"></A>
<H2><A HREF="#consequences"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Collaborations</H2>

<UL>

<A NAME="auto1032"></A>
<LI>When a client issues a request, the request propagates along the chain
until a ConcreteHandler object takes responsibility for handling it.

</UL>

<A NAME="consequences"></A>
<H2><A HREF="#implementation"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Consequences</H2> 

<A NAME="auto1033"></A>
<P>Chain of Responsibility has the following benefits and liabilities:</P>

<OL>

<A NAME="auto1034"></A>
<LI><EM>Reduced coupling.</EM>
The pattern frees an object from knowing which other object handles a
request.  An object only has to know that a request will be handled
"appropriately." Both the receiver and the sender have no explicit
knowledge of each other, and an object in the chain doesn't have to
know about the chain's structure.

<A NAME="auto1035"></A>
<P>As a result, Chain of Responsibility can simplify object
interconnections.  Instead of objects maintaining references to all
candidate receivers, they keep a single reference to their successor.</P></LI>

<A NAME="auto1036"></A>
<P></P>

<A NAME="auto1037"></A>
<LI><EM>Added flexibility in assigning responsibilities to objects.</EM>
Chain of Responsibility gives you added flexibility in distributing
responsibilities among objects.  You can add or change
responsibilities for handling a request by adding to or otherwise
changing the chain at run-time.  You can combine this with subclassing
to specialize handlers statically.</LI>

<A NAME="auto1038"></A>
<P></P>

<A NAME="guarantee-receipt"></A>
<LI><EM>Receipt isn't guaranteed.</EM>
Since a request has no explicit receiver, there's no <EM>guarantee</EM>
it'll be handled&#151;the request can fall off the end of the chain
without ever being handled.  A request can also go unhandled when the
chain is not configured properly.</LI>

</OL>

<A NAME="implementation"></A>
<H2><A HREF="#samplecode"><IMG SRC="gifsb/down3.gif" BORDER=0></A> Implementation</H2> 

<A NAME="auto1039"></A>
<P>Here are implementation issues to consider in Chain of Responsibility:</P>

<OL>

<A NAME="auto1040"></A>
<LI><EM>Implementing the successor chain.</EM>
There are two possible ways to implement the successor chain:</LI>

<A NAME="auto1041"></A>
<P></P>

<OL>

<LI TYPE=a>Define new links (usually in the Handler, but ConcreteHandlers
could define them instead).</LI>

<A NAME="auto1042"></A>
<P></P>

<LI TYPE=a>Use existing links.</LI>

</OL>

<A NAME="auto1043"></A>
<P>Our examples so far define new links, but often you can use existing
object references to form the successor chain. For example, parent
references in a part-whole hierarchy can define a part's successor.  A
widget structure might already have such links.
<A HREF="pat4cfs.htm" TARGET="_mainDisplayFrame">Composite&nbsp;(163)</A> discusses parent references in more
detail.</P>

<A NAME="auto1044"></A>
<P>Using existing links works well when the links support the chain you
need.  It saves you from defining links explicitly, and it saves
space.  But if the structure doesn't reflect the chain of
responsibility your application requires, then you'll have to define
redundant links.</P></LI>

<A NAME="auto1045"></A>
<P></P>

<A NAME="succ-connect"></A>
<LI><EM>Connecting successors.</EM>
If there are no preexisting references for defining a chain, then you'll
have to introduce them yourself. In that case, the Handler not only
defines the interface for the requests but usually maintains the
successor as well.  That lets the handler provide a default
implementation of HandleRequest that forwards the request to the
successor (if any).  If a ConcreteHandler subclass isn't interested
in the request, it doesn't have to override the forwarding operation,
since its default implementation forwards unconditionally.

<A NAME="auto1046"></A>
<P>Here's a HelpHandler base class that maintains a successor link:</P>

<A NAME="auto1047"></A>
<PRE>
    class HelpHandler {
    public:
        HelpHandler(HelpHandler* s) : _successor(s) { }
        virtual void HandleHelp();
    private:
        HelpHandler* _successor;
    };
    
    void HelpHandler::HandleHelp () {
        if (_successor) {
            _successor->HandleHelp();
        }
    }
</PRE>

<A NAME="auto1048"></A>
<P></P>

<A NAME="represent-request"></A>
<LI><EM>Representing requests.</EM>
Different options are available for representing requests.  In the
simplest form, the request is a hard-coded operation invocation, as in
the case of HandleHelp. This is convenient and safe, but you can
forward only the fixed set of requests that the Handler class defines.</P>

<A NAME="auto1049"></A>
<P>An alternative is to use a single handler function that takes a
request code (e.g., an integer constant or a string) as parameter.
This supports an open-ended set of requests. The only requirement is
that the sender and receiver agree on how the request should be

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -