ghytred.com


NewsLook for Outlook

Patterns and OO
CommandPattern
The Web Site you seek
Cannot be located, so
Waste your time here

Contents

Command

From GoF Encapsulate a request as an object, thereby letting you parameterise clients with different requests, queue or log requests, and support undo and redo operations.

If there is a task which needs to be done, but who does that task and in what way is not known at compile time, Command is a good pattern to use.

When the Invoker class was created, its creator will have given it an appropriate Concrete Command object. When the task needs to be done at run-time, Invoker will call the Execute method passing appropriate parameters.

There are many examples of this pattern in the .NET Framework; one which springs to mind is reading or writing from a Stream. Most classes which do this will take a Stream as a parameter; Stream is an abstract class, with descendents like FileStream, TextStream, MemoryStream etc. These are the concrete commands which read or write to different types of stream. See for instance XmlTextWriter.

Commands can be linked together via a �MacroCommand�. A MacroCommand is a Concrete Command (it inherits from Command above), but its Execute method calls the Execute methods of a number of other Concrete Commands which it contains.

Note the Receiver object in the diagram. This is the object on which the Command is to do its work. It can be set either as a parameter in the call to Execute, or by the creator of the ConcreteCommand as a parameter to the constructor. In the latter case, the creator would probably not be the class which actually calls Execute, but another class which knows which type of Concrete Command is needed by the Invoker. (The Invoker could be a non-specific object such as a MenuItem or Button which only knows that when it is clicked it should call Execute on its Command. This allows maximum reusability of the Invoker.)

Another common diagram of Command is as follows:

This fleshes out the original GoF diagram by including collaborations with the client which are implicit in the GoF text. Remember, though, that these patterns do not exist as straight-jackets but inspirations.

Consequences:

  • Decouples the object invoking an operation from the object that knows how to do it
  • Allows a Client to vary the operations an invoker instigates without changing the invoker
  • Links something which requires an action (the Invoker) with the object which can carry it out (the Receiver) while avoiding coupling them together.
  • The Command can contain a wide range of intelligence. At one end of the range, it passes on a call to the Receiver and does nothing else. At the other it may do a very complex set of operations without having a receiver at all.

Notes from Vince Huston's excellent pages:

  • Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Command normally specifies a sender-receiver connection with a subclass.
  • Chain of Responsibility can use Command to represent requests as objects. [GOF, p349].
  • Command and Memento act as magic tokens to be passed around and invoked at a later time. In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time. Polymorphism is important to Command, but not to Memento because its interface is so narrow that a memento can only be passed as a value. [GOF, p346]
  • Command can use Memento to maintain the state required for an undo operation. [GOF, p242]
  • MacroCommands can be implemented with Composite. [GOF, p242]
  • A Command that must be copied before being placed on a history list acts as a Prototype. [GOF, p242]
  • POSA's Command Processor pattern describes the scaffolding Command needs to support full multilevel undo and redo. [Vlissides, Java Report, Nov 2000, p80]

From CodePro Java Patterns

  • 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 fulfil the request there.
  • 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.
  • 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 re-executing them with the Execute operation.
  • structure a system around high-level operations built on primitives operations. Such a structure is common in information systems that support transactions. 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.

Return to top