Chapter18 Command
Chapter18 Command
Contents
18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
18.4 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
18.4.1 TV Remote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
18.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1
18.1 Introduction
This Lecture Note introduces the Command design pattern. The pattern will be illus-
trated using a TV remote as an example.
18.2.1 Identification
Name Classification Strategy
Command Behavioural Delegation
Intent
Encapsulate a request as an object, thereby letting you parameterise clients
with different requests, queue or log requests, and support undoable operations.
([1]:263)
18.2.2 Problem
Used to modify existing interfaces to make it work after it has been designed.
18.2.3 Structure
18.2.4 Participants
Command
ConcreteCommand
2
Client (Application)
Invoker
Receiver
• knows how to perform the operations associated with carrying out a request.
Any class may serve as a Receiver.
Composite:
MacroCommands can be implemented when combining command with Composite.
Memento:
Makes use of Command to keep state the command requires to undo its effect.
Prototype:
A command that must be copied before being placed on the history list acts as a
Prototype.
18.4 Example
18.4.1 TV Remote
This example will model a TV remote. The remote has two buttons, one to flip through
channels and one to switch the TV on and off.
Listing 1: Implementation of a TV remote
#include <i o s t r e a m >
using namespace s t d ;
c l a s s TV {
public :
s t a t i c void a c t i o n ( char∗ s ) { cout<<s<<e n d l ; } ;
};
c l a s s Command {
3
Figure 2: TV remote example
public :
v i r t u a l void e x e c u t e ( ) = 0 ;
v i r t u a l char∗ g e t S t a t u s ( ) = 0 ;
};
4
};
void e x e c u t e ( ) {
c h a n n e l = ( c h a n n e l ==5)?1:++ c h a n n e l ;
TV : : a c t i o n ( g e t S t a t u s ( ) ) ;
};
char∗ g e t S t a t u s ( ) {
char∗ s t r = new char [ 2 0 ] ;
s t r c p y ( s t r , ”The d e v i c e i s on c h a n n e l ” ) ;
switch ( c h a n n e l ) {
case 1 : s t r c a t ( s t r , ”1” ) ; break ;
case 2 : s t r c a t ( s t r , ”2” ) ; break ;
case 3 : s t r c a t ( s t r , ”3” ) ; break ;
case 4 : s t r c a t ( s t r , ”4” ) ; break ;
case 5 : s t r c a t ( s t r , ”5” ) ; break ;
}
return s t r ;
};
private :
int c h a n n e l ;
};
c l a s s TVRemote { // I n v o k e r
public :
TVRemote ( ) {
b u t t o n s [ 0 ] = new OnOffCommand ( f a l s e ) ;
b u t t o n s [ 1 ] = new NextChannelCommand ( ) ;
};
void onPushed ( ) {
b u t t o n s [0]−> e x e c u t e ( ) ;
};
void channelChanged ( ) {
b u t t o n s [1]−> e x e c u t e ( ) ;
};
private :
Command∗ b u t t o n s [ 2 ] ;
};
int main ( ) {
TVRemote∗ t v r = new TVRemote ;
tvr −>onPushed ( ) ;
tvr −>channelChanged ( ) ;
tvr −>channelChanged ( ) ;
tvr −>channelChanged ( ) ;
5
tvr −>onPushed ( ) ;
tvr −>channelChanged ( ) ;
tvr −>channelChanged ( ) ;
return 0 ;
}
18.5 Exercises
1. Consider the following code that illustrated the command pattern. Draw the UML
class diagram.
Listing 3: Implementation of the LightSwitch
c l a s s Fan
{
public :
void s t a r t R o t a t e ( ) { cout << ”Fan i s r o t a t i n g ” << e n d l ; }
void s t o p R o t a t e ( ) { cout << ”Fan i s not r o t a t i n g ” << e n d l ; }
};
class Light
{
public :
void turnOn ( ) { cout << ” L i g h t i s on ” << e n d l ; }
void t u r n O f f ( ) { cout << ” L i g h t i s o f f ” << e n d l ; }
};
c l a s s Command
{
public :
v i r t u a l void e x e c u t e ( ) = 0 ;
};
6
{
public :
LightOffCommand ( L i g h t ∗ L) { myLight = L ; }
void e x e c u t e ( ) { myLight −> t u r n O f f ( ) ; }
private :
L i g h t ∗ myLight ;
};
c l a s s Switch
{
public :
Switch (Command∗ up , Command∗ down )
{
upCommand = up ;
downCommand = down ;
}
private :
Command∗ upCommand ;
Command∗ downCommand ;
};
int main ( )
{
L i g h t ∗ t e s t L i g h t = new L i g h t ( ) ;
Fan∗ t e s t F a n = new Fan ( ) ;
7
LightOnCommand∗ testLiOnCmnd = new LightOnCommand ( t e s t L i g h t ) ;
LightOffCommand∗ testLiOffCmnd = new LightOffCommand ( t e s t L i g h t ) ;
FanOnCommand∗ testFaOnCmnd = new FanOnCommand( t e s t F a n ) ;
FanOffCommand∗ testFaOffCmnd = new FanOffCommand ( t e s t F a n ) ;
l i g h t S w i t c h −> f l i p U p ( ) ;
l i g h t S w i t c h −> flipDown ( ) ;
f a n S w i t c h −> f l i p U p ( ) ;
f a n S w i t c h −> flipDown ( ) ;
/∗ ∗ As opposed t o
t e s t L i g h t −> turnOn ( ) ;
t e s t L i g h t −> t u r n O f f ( ) ;
t e s t F a n −> s t a r t R o t a t e ( ) ;
t e s t F a n −> s t o p R o t a t e ( ) ;
∗/
return 0 ;
}
References
[1] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design patterns :
elements of reusable object-oriented software. Addison-Wesley, Reading, Mass, 1995.