Department of Computer Science
Tackling Design Patterns
Chapter 18: Command Design Pattern
Copyright c 2016 by Linda Marshall and Vreda Pieterse. All rights reserved.
Contents
18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
18.2 Command Design Pattern . . . . . . . . . . . . . . . . . . . . . . . . 2
18.2.1 Identification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
18.2.2 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
18.2.3 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
18.2.4 Participants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
18.3 Comand Pattern Explained . . . . . . . . . . . . . . . . . . . . . . . . 3
18.3.1 Related Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
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 Command Design Pattern
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
Figure 1: The structure of the Command Design Pattern
18.2.4 Participants
Command
• declares an interface for executing an operation.
ConcreteCommand
• defines a binding between a Receiver object and an action.
• implements execute() by invoking the corresponding operation(s) on Receiver.
2
Client (Application)
• creates a ConcreteCommand object and sets its receiver.
Invoker
• asks the command to carry out the request.
Receiver
• knows how to perform the operations associated with carrying out a request.
Any class may serve as a Receiver.
18.3 Comand Pattern Explained
18.3.1 Related Patterns
Chain of Responsibility:
Makes use of Command to represent requests as objects.
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 ;
};
c l a s s OnOffCommand : public Command {
public :
OnOffCommand ( bool s ) : on ( s ) { } ;
void e x e c u t e ( ) {
on = on ? f a l s e : true ;
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 ” ) ;
s t r c a t ( s t r , ( on==f a l s e ? ” o f f ” : ”on” ) ) ;
return s t r ;
};
private :
bool on ;
};
c l a s s NextChannelCommand : public Command {
public :
NextChannelCommand ( ) {
channel = 1 ;
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 ;
}
Sample output for the program is given by:
Listing 2: TV Remote Sample Output
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 ;
};
c l a s s LightOnCommand : public Command
{
public :
LightOnCommand ( L i g h t ∗ L) { myLight = L ; }
void e x e c u t e ( ) { myLight −> turnOn ( ) ; }
private :
L i g h t ∗ myLight ;
};
c l a s s LightOffCommand : public Command
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 FanOnCommand : public Command
{
public :
FanOnCommand ( Fan∗ f ) { myFan = f ; }
void e x e c u t e ( ) { myFan −> s t a r t R o t a t e ( ) ; }
private :
Fan∗ myFan ;
};
c l a s s FanOffCommand : public Command
{
public :
FanOffCommand ( Fan∗ f ) { myFan = f ; }
void e x e c u t e ( ) {myFan −> s t o p R o t a t e ( ) ; }
private :
Fan∗ myFan ;
};
c l a s s Switch
{
public :
Switch (Command∗ up , Command∗ down )
{
upCommand = up ;
downCommand = down ;
}
void f l i p U p ( ) { upCommand −> e x e c u t e ( ) ; } ;
void flipDown ( ) {downCommand −> e x e c u t e ( ) ; } ;
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 ) ;
Switch ∗ l i g h t S w i t c h = new Switch ( testLiOnCmnd , testLiOffCmnd ) ;
Switch ∗ f a n S w i t c h = new Switch ( testFaOnCmnd , testFaOffCmnd ) ;
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.