📄 pat5b.htm
字号:
<HTML>
<HEAD><TITLE>Command</TITLE>
<SCRIPT>
function setFocus() {
if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {
return;
} else {
self.focus();
}
}
</SCRIPT>
</HEAD>
<BODY BGCOLOR = #FFFFFF
onLoad="setFocus()";>
<A NAME="top"></A>
<A NAME="Command"></A>
<A NAME="intent"></A>
<H2><A HREF="#alsoknownas"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next:
Also Known As"></A> Intent</H2>
<A NAME="auto1000"></A>
<P>Encapsulate a request as an object, thereby letting you parameterize
clients with different requests, queue or log requests, and support
undoable operations.</P>
<A NAME="alsoknownas"><A>
<H2><A HREF="#motivation"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next:
Motivation"></A> Also Known As</H2>
<A NAME="auto1001"></A>
<P>Action, Transaction</P>
<A NAME="motivation"></A>
<H2><A HREF="#applicability"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0
ALT="next: Applicability"></A> Motivation</H2>
<A NAME="auto1002"></A>
<P>Sometimes it's necessary to issue requests to objects without knowing
anything about the operation being requested or the receiver of the
request. For example, user interface toolkits include objects like
buttons and menus that carry out a request in response to user input.
But the toolkit can't implement the request explicitly in the button
or menu, because only applications that use the toolkit know what
should be done on which object. As toolkit designers we have no way
of knowing the receiver of the request or the operations that will
carry it out.</P>
<A NAME="toolkit2"></A>
<P>The Command pattern lets toolkit objects make requests of unspecified
application objects by turning the request itself into an object. This
object can be stored and passed around like other objects. The key to
this pattern is an abstract Command class, which declares an interface
for executing operations. In the simplest form this interface
includes an abstract Execute operation. Concrete Command subclasses
specify a receiver-action pair by storing the receiver as an instance
variable and by implementing Execute to invoke the request. The
receiver has the knowledge required to carry out the request.</P>
<A NAME="233c"></A>
<P ALIGN=CENTER><IMG SRC="comma081.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/comma081.gif"></P>
<A NAME="document-234"></A>
<P>Menus can be implemented easily with Command objects. Each choice in
a Menu is an instance of a MenuItem class. An Application class creates
these menus and their menu items along with the rest of the user interface.
The Application class also keeps track of Document objects that a user has
opened.</P>
<A NAME="auto1003"></A>
<P>The application configures each MenuItem with an instance of a
concrete Command subclass. When the user selects a MenuItem, the
MenuItem calls Execute on its command, and Execute carries out the
operation. MenuItems don't know which subclass of Command they use.
Command subclasses store the receiver of the request and invoke one or
more operations on the receiver.</P>
<A NAME="auto1004"></A>
<P>For example, PasteCommand supports pasting text from the clipboard
into a Document. PasteCommand's receiver is the Document object it is
supplied upon instantiation. The Execute operation invokes Paste on
the receiving Document.</P>
<A NAME="234c"></A>
<P ALIGN=CENTER><IMG SRC="comma078.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/comma078.gif"></P>
<A NAME="auto1005"></A>
<P>OpenCommand's Execute operation is different: it prompts the user
for a document name, creates a corresponding Document object, adds the
document to the receiving application, and opens the document.</P>
<P ALIGN=CENTER><IMG SRC="comma079.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/comma079.gif">
<A NAME="macrocommand"></A>
<A NAME="sequence-request"></A>
<P>Sometimes a MenuItem needs to execute a <EM>sequence</EM> of commands.
For example, a MenuItem for centering a page at normal size could be
constructed from a CenterDocumentCommand object and a
NormalSizeCommand object. Because it's common to string commands
together in this way, we can define a MacroCommand class to allow a
MenuItem to execute an open-ended number of commands. MacroCommand is
a concrete Command subclass that simply executes a sequence of
Commands. MacroCommand has no explicit receiver, because the commands
it sequences define their own receiver.</P>
<A NAME="command-eg-macro"></A>
<P ALIGN=CENTER><IMG SRC="comma080.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/comma080.gif"></P>
<A NAME="auto1006"></A>
<P>In each of these examples, notice how the Command pattern decouples
the object that invokes the operation from the one having the
knowledge to perform it. This gives us a lot of flexibility in
designing our user interface. An application can provide both a menu
and a push button interface to a feature just by making the menu and
the push button share an instance of the same concrete Command subclass.
We can replace commands dynamically, which would be useful for
implementing context-sensitive menus. We can also support command
scripting by composing commands into larger ones. All of this is
possible because the object that issues a request only needs to know
how to issue it; it doesn't need to know how the request will be carried out.</P>
<A NAME="applicability"></A>
<H2><A HREF="#structure"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next:
Structure"></A> Applicability</H2>
<A NAME="auto1007"></A>
<P>Use the Command pattern when you want to</P>
<UL>
<A NAME="auto1008"></A>
<LI> parameterize objects by an action to perform, as MenuItem objects
did above. You can express such parameterization in a procedural
language with a <STRONG>callback</STRONG> function, that is, a function
that's registered somewhere to be called at a later point.
Commands are an object-oriented replacement for callbacks.</LI>
<A NAME="auto1009"></A>
<P></P>
<A NAME="request-sequence"></A>
<LI> specify, queue, and execute requests at different times. A
Command object can have a lifetime independent of the original
request. If the receiver of a request can be represented in an
address space-independent way, then you can transfer a command
object for the request to a different process and fulfill the
request there.</LI>
<A NAME="auto1010"></A>
<P></P>
<A NAME="support-undo"></A>
<LI> support undo. The Command's Execute operation can store state for
reversing its effects in the command itself. The Command interface
must have an added Unexecute operation that reverses the effects
of a previous call to Execute. Executed commands are stored in a
history list. Unlimited-level undo and redo is achieved by
traversing this list backwards and forwards calling Unexecute and
Execute, respectively.</LI>
<A NAME="auto1011"></A>
<P></P>
<A NAME="auto1012"></A>
<LI> support logging changes so that they can be reapplied in case of a
system crash. By augmenting the Command interface with load and
store operations, you can keep a persistent log of changes.
Recovering from a crash involves reloading logged commands from
disk and reexecuting them with the Execute operation.</LI>
<A NAME="auto1013"></A>
<P></P>
<A NAME="def-transaction"></A>
<LI> structure a system around high-level operations built on
primitives operations. Such a structure is common in information
systems that support <STRONG>transactions</STRONG>. A transaction
encapsulates a set of changes to data. The Command pattern offers
a way to model transactions. Commands have a common interface,
letting you invoke all transactions the same way. The pattern
also makes it easy to extend the system with new transactions.</LI>
</UL>
<A NAME="structure"></A>
<H2><A HREF="#participants"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next:
Participants"></A> Structure</H2>
<P ALIGN=CENTER><IMG SRC="command.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/command.gif"></P>
<A NAME="participants"></A>
<H2><A HREF="#collaborations"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0
ALT="next: Collaborations"></A> Participants</H2>
<UL>
<A NAME="auto1014"></A>
<LI><B>Command</B>
<A NAME="auto1015"></A>
<P></P>
<UL>
<A NAME="auto1016"></A>
<LI>declares an interface for executing an operation.</LI>
</UL>
<A NAME="auto1017"></A>
<P></P>
<A NAME="auto1018"></A>
<LI><B>ConcreteCommand</B> (PasteCommand, OpenCommand)
<A NAME="auto1019"></A>
<P></P>
<UL>
<A NAME="auto1020"></A>
<LI>defines a binding between a Receiver object and an action.</LI>
<A NAME="auto1021"></A>
<P><!-- extra space --></P>
<A NAME="auto1022"></A>
<LI>implements Execute by invoking the corresponding operation(s)
on Receiver.</LI>
</UL>
<A NAME="auto1023"></A>
<P></P>
<A NAME="auto1024"></A>
<LI><B>Client</B> (Application)</LI>
<A NAME="auto1025"></A>
<P></P>
<UL>
<A NAME="auto1026"></A>
<LI>creates a ConcreteCommand object and sets its receiver.</LI>
</UL>
<A NAME="auto1027"></A>
<P></P>
<A NAME="auto1028"></A>
<LI><B>Invoker</B> (MenuItem)
<A NAME="auto1029"></A>
<P></P>
<UL>
<A NAME="auto1030"></A>
<LI>asks the command to carry out the request.</LI>
</UL>
<A NAME="auto1031"></A>
<P></P>
<A NAME="receiver-part-command"></A>
<LI><B>Receiver</B> (Document, Application)
<A NAME="auto1032"></A>
<P></P>
<UL>
<A NAME="auto1033"></A>
<LI>knows how to perform the operations associated with carrying
out a request. Any class may serve as a Receiver.</LI>
</UL>
</UL>
<A NAME="collaborations"></A>
<H2><A HREF="#consequences"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0
ALT="next: Consequences"></A> Collaborations</H2>
<UL>
<A NAME="auto1034"></A>
<LI>The client creates a ConcreteCommand object and specifies its receiver.</LI>
<A NAME="auto1035"></A>
<P></P>
<A NAME="auto1036"></A>
<LI>An Invoker object stores the ConcreteCommand object.</LI>
<A NAME="auto1037"></A>
<P></P>
<A NAME="auto1038"></A>
<LI>The invoker issues a request by calling Execute on the command. When
commands are undoable, ConcreteCommand stores state for undoing the
command prior to invoking Execute.</LI>
<A NAME="auto1039"></A>
<P></P>
<A NAME="auto1040"></A>
<LI>The ConcreteCommand object invokes operations on its receiver to carry
out the request.</LI>
</UL>
<A NAME="auto1041"></A>
<P>The following diagram shows the interactions between these objects.
It illustrates how Command decouples the invoker from the receiver
(and the request it carries out).</P>
<A NAME="command-237i"></A>
<P ALIGN=CENTER><IMG SRC="comma077.gif" tppabs="http://ultra/development/DesignPatterns/hires/Pictures/comma077.gif"></P>
<A NAME="consequences"></A>
<H2><A HREF="#implementation"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0
ALT="next: Implementation"></A> Consequences</H2>
<A NAME="auto1042"></A>
<P>The Command pattern has the following consequences:</P>
<OL>
<A NAME="auto1043"></A>
<LI>Command decouples the object that invokes the operation from the one
that knows how to perform it.</LI>
<A NAME="auto1044"></A>
<P></P>
<A NAME="auto1045"></A>
<LI>Commands are first-class objects. They can be manipulated and extended
like any other object.</LI>
<A NAME="auto1046"></A>
<P></P>
<A NAME="auto1047"></A>
<LI>You can assemble commands into a composite command. An example is the
MacroCommand class described earlier. In general, composite commands
are an instance of the <A HREF="pat4cfs.htm" tppabs="http://ultra/development/DesignPatterns/hires/pat4cfs.htm" TARGET="_mainDisplayFrame">Composite (163)</A> pattern.</LI>
<A NAME="auto1048"></A>
<P></P>
<A NAME="auto1049"></A>
<LI>It's easy to add new Commands, because you don't have to change
existing classes.</LI>
</OL>
<A NAME="implementation"></A>
<H2><A HREF="#samplecode"><IMG SRC="down3.gif" tppabs="http://ultra/development/DesignPatterns/hires/gifsb/down3.gif" BORDER=0 ALT="next:
Sample Code"></A> Implementation</H2>
<A NAME="auto1050"></A>
<P>Consider the following issues when implementing the Command pattern:</P>
<OL>
<A NAME="auto1051"></A>
<LI><EM>How intelligent should a command be?</EM>
A command can have a wide range of abilities. At one extreme it
merely defines a binding between a receiver and the actions that carry
out the request. At the other extreme it implements everything itself
without delegating to a receiver at all. The latter extreme is useful
when you want to define commands that are independent of existing
classes, when no suitable receiver exists, or when a command knows its
receiver implicitly. For example, a command that creates another
application window may be just as capable of creating the window as
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -