📄 disc5-1.htm
字号:
<!-- saved from url=(0022)http://internet.e-mail -->
<HTML>
<HEAD><TITLE>Discussion of Behavioral Patterns</TITLE>
<SCRIPT>
function setFocus() {
if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {
return;
} else {
self.focus();
}
}
</SCRIPT>
</HEAD>
<BODY TOPMARGIN = 4
LEFTMARGIN = 4
BGCOLOR = #FFFFFF
onLoad="setFocus()";>
<A NAME="top"></A>
<A NAME="disc5-1"></A>
<a name="encap"></a>
<H2><A HREF="#objects"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/gifsb/down3.gif" BORDER=0 ALT="next: Objects as
Arguments"></A> Encapsulating Variation</H2>
<A NAME="disc5-2"></A>
<P>Encapsulating variation is a theme of many behavioral patterns. When
an aspect of a program changes frequently, these patterns define an
object that encapsulates that aspect. Then other parts of the program
can collaborate with the object whenever they depend on that aspect.
The patterns usually define an abstract class that describes the
encapsulating object, and the pattern derives its name from that
object.<A NAME="fn12"></A><A HREF="#footnote12"><SUP>12</SUP></A>
For example,</P>
<UL>
<A NAME="disc5-3"></A>
<LI>a Strategy object encapsulates an algorithm (<A HREF="pat5ifs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5ifs.htm" TARGET="_mainDisplayFrame">Strategy (315)</A>),</LI>
<P></P>
<A NAME="disc5-4"></A>
<LI>a State object encapsulates a state-dependent behavior
(<A HREF="pat5hfs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5hfs.htm" TARGET="_mainDisplayFrame">State (305)</A>),</LI>
<P></P>
<A NAME="disc5-5"></A>
<LI>a Mediator object encapsulates the protocol between
objects (<A HREF="pat5efs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5efs.htm" TARGET="_mainDisplayFrame">Mediator (273)</A>), and</LI>
<P></P>
<A NAME="disc5-6"></A>
<LI>an Iterator object encapsulates the way you access and traverse the
components of an aggregate object (<A HREF="pat5dfs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5dfs.htm"
TARGET="_mainDisplayFrame">Iterator (257)</A>).</LI>
</UL>
<A NAME="disc5-7"></A>
<P>These patterns describe aspects of a program that are likely to
change. Most patterns have two kinds of objects: the new object(s)
that encapsulate the aspect, and the existing object(s) that use the
new ones. Usually the functionality of new objects would be an
integral part of the existing objects were it not for the pattern. For
example, code for a Strategy would probably be wired into the
strategy's Context, and code for a State would be implemented directly
in the state's Context.</P>
<A NAME="disc5-8"></A>
<P>But not all object behavioral patterns partition functionality like
this. For example, <A HREF="pat5afs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5afs.htm" TARGET="_mainDisplayFrame">Chain of Responsibility (223)</A> deals
with an arbitrary number of objects (i.e., a chain), all of which may
already exist in the system. </P>
<A NAME="disc5-9"></A>
<P>Chain of Responsibility illustrates another difference in behavioral
patterns: Not all define static communication relationships between
classes. Chain of Responsibility prescribes communication between an
open-ended number of objects. Other patterns involve objects that are
passed around as arguments.</P>
<A NAME="disc5-10"></A>
<A NAME="objects"></A>
<H2><A HREF="#media-vs-obsrv"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/gifsb/down3.gif" BORDER=0 ALT="next: Should
Communication be Encapsulated or Distributed?"></A> Objects as Arguments</H2>
<A NAME="disc5-11"></A>
<P>Several patterns introduce an object that's <EM>always</EM> used
as an argument. One of these is
<A HREF="pat5kfs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5kfs.htm" TARGET="_mainDisplayFrame">Visitor (331)</A>.
A Visitor object is the
argument to a polymorphic Accept operation on the objects it visits.
The visitor is never considered a part of those objects, even though
the conventional alternative to the pattern is to distribute Visitor
code across the object structure classes.</P>
<A NAME="disc5-12"></A>
<A NAME="magictoken"></A>
<P>Other patterns define objects that act as magic tokens to be passed
around and invoked at a later time. Both
<A HREF="pat5bfs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5bfs.htm" TARGET="_mainDisplayFrame">Command (233)</A>
and
<A HREF="pat5ffs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5ffs.htm" TARGET="_mainDisplayFrame">Memento (283)</A>
fall into this category. In Command,
the token represents a request; in Memento, it represents the internal
state of an object at a particular time.
In both cases, the token can have a complex internal representation,
but the client is never aware of it. But even here there are
differences. Polymorphism is important in the Command pattern,
because executing the Command object is a polymorphic operation. In
contrast, the Memento interface is so narrow that a memento can only
be passed as a value. So it's likely to present no polymorphic
operations at all to its clients.</P>
<A NAME="disc5-13"></A>
<A NAME="media-vs-obsrv"></A>
<H2><A HREF="#decouple-sandr"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/gifsb/down3.gif" BORDER=0 ALT="next: Decoupling
Senders and Receivers"></A> Should Communication be Encapsulated or Distributed?</H2>
<A NAME="disc5-14"></A>
<P><A HREF="pat5efs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5efs.htm" TARGET="_mainDisplayFrame">Mediator (273)</A>
and
<A HREF="pat5gfs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat5gfs.htm" TARGET="_mainDisplayFrame">Observer (293)</A> are
competing patterns. The difference between them is that Observer
distributes communication by introducing Observer and Subject objects,
whereas a Mediator object encapsulates the communication between other
objects.</P>
<A NAME="disc5-15"></A>
<P>In the Observer pattern, there is no single object that encapsulates a
constraint. Instead, the Observer and the Subject must cooperate to
maintain the constraint. Communication patterns are determined by the
way observers and subjects are interconnected: a single subject
usually has many observers, and sometimes the observer of one subject
is a subject of another observer. The Mediator pattern centralizes
rather than distributes. It places the responsibility for maintaining
a constraint squarely in the mediator.</P>
<A NAME="disc5-16"></A>
<P>We've found it easier to make reusable Observers and Subjects than to
make reusable Mediators. The Observer pattern promotes partitioning
and loose coupling between Observer and Subject, and that leads to
finer-grained classes that are more apt to be reused. </P>
<A NAME="disc5-17"></A>
<P>On the other hand, it's easier to understand the flow of communication
in Mediator than in Observer. Observers and subjects are usually
connected shortly after they're created, and it's hard to see how they
are connected later in the program. If you know the Observer pattern,
then you understand that the way observers and subjects are connected
is important, and you also know what connections to look for.
However, the indirection that Observer introduces will still make a
system harder to understand.</P>
<A NAME="disc5-18"></A>
<P>Observers in Smalltalk can be parameterized with messages to access
the Subject state, and so they are even more reusable than they are in
C++. This makes Observer more attractive than Mediator in Smalltalk.
Thus a Smalltalk programmer will often use Observer where a C++
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -