Professional Documents
Culture Documents
Command Pattern
Command Pattern
2
Outline
Requirements Statement
Initial Design and Its Problems
Design Process
Refactored Design after Design Process
Another Example
Recurrent Problems
Intent
Command Pattern Structure
Homework
3
Remote Control
5
Requirements Statement2
Furthermore, the remote control also controls light
that can be switched on and off.
{
if (!stereo.isOn()) { Stereo
stereo.on();
stereo.setCD(); on()
stereo.setVolume(); RemoteControl setCD()
} setVolume()
} Stereo stereo isOn(): boolean
Light light
stereoSwitch() Light
{ lightSwitch()
if (!light.isOn()) {
light.on(); on()
} else { off()
light.off(); isOn(): boolean
}
}
6
Initial Design - Class Diagram
{
if (!stereo.isOn()) { Stereo
stereo.on();
stereo.setCD(); on()
stereo.setVolume(); RemoteControl setCD()
} setVolume()
} Stereo stereo isOn(): boolean
Light light
stereoSwitch() Light
{ lightSwitch()
if (!light.isOn()) {
light.on(); on()
} else { off()
light.off(); isOn(): boolean
}
}
7
Problems with Initial Design
{
if (!stereo.isOn()) { Stereo
stereo.on();
stereo.setCD(); on()
stereo.setVolume(); RemoteControl setCD()
} setVolume()
} Stereo stereo isOn(): boolean
Light light
stereoSwitch() Light
{ lightSwitch()
if (!light.isOn()) {
light.on(); on()
} else { off()
light.off(); isOn(): boolean
}
}
8
Design Process for Change
Need abstraction?
Act-1: Encapsulate
No What Varies, methods No
and its corresponding
attributes Need composition?
Yes Yes
Act-3: Compose or
Delegate Abstract Expose new interfaces?
Design Principle: Depend on
abstractions. Do not depend on Behaviors
concrete classes.
Yes No
9
Act-1: Encapsulate What Varies
Stereo stereo }
Light light
stereoSwitch()
lightSwitch()
{
LightOnCommand if (!light.isOn()) {
light.on();
Light light } else {
light.off();
execute() }
}
10
Act-2: Abstract Common Behaviors
<<interface>>
Command
StereoOnCommand LightOnCommand
execute() execute()
11
Act-3: Compose Abstract Behaviors
12
Refactored Design after Design Process
RemoteControl <<interface>>
Command
Command cmd[]
execute()
setCommand(int index, Command cmd)
{
doCommand(int index)
cmd[index].execute();
}
13
Cut, Copy, Paste
on a Document
doc
Editor Document
15
Requirements Statement2
A menu in the editor application contains some
menu items which performs three specific
operations such as cut, copy, and paste on a
document.
doc
Editor EditMenu * <<interface>>
…
MenuItem
clicked() doc.copy();
Document …
doc.paste();
cut()
copy()
paste()
16
Initial Design
doc
Editor EditMenu * <<interface>>
MenuItem
clicked()
… …
doc.paste(); doc.copy();
Document
cut()
copy()
paste()
17
Problems with Initial Design
doc <<interface>>
Editor EditMenu * MenuItem
clicked()
… …
doc.paste(); doc.copy();
Document
cut() Problem: Cut, Copy, and Paste may not only be used in the
copy() EditMenu. Once we want to use the same cut, copy, and
paste() paste features on a receiver (Document) in other UI widgets,
we will have duplicated code.
18
Design Process for Change
Need abstraction?
Act-1: Encapsulate
No What Varies, methods No
and its corresponding
attributes Need composition?
Yes Yes
Act-3: Compose or
Delegate Abstract Expose new interfaces?
Design Principle: Depend on
abstractions. Do not depend on Behaviors
concrete classes.
Yes No
19
Act-1: Encapsulate What Varies
doc <<interface>>
Editor EditMenu * MenuItem
clicked()
20
Act-2: Abstract Common Behaviors
Command
2.2 Abstract common
doc behaviors with a same
… execute() signature into abstract
doc.paste();
class through inheritance
21
Act-3: Compose Abstract Behaviors
in order to keep a
CutMenuItem CutCommand
Command reference. clicked() execute()
CopyMenuItem CopyCommand
clicked() execute()
PasteMenuItem PasteCommand
Document clicked() execute()
cut() …
copy() doc.copy();
paste() …
doc.paste();
22
Refactored Design after Design Process
doc command
Editor EditMenu MenuItem * Command
clicked() doc
… execute()
doc.cut();
CutMenuItem CutCommand
clicked() execute()
CopyMenuItem CopyCommand
clicked() execute()
PasteMenuItem PasteCommand
Document clicked() execute()
cut() …
copy() doc.copy();
paste() …
doc.paste();
23
Recurrent Problem
The invoker object is subject to be modified once
the set of the actions on a receiver is changed
Sometimes it's necessary to issue requests to objects
without knowing anything about the operation being
requested or the receiver of the request.
24
Command Pattern
Intent
Encapsulate a request as an object, thereby letting you
parameterize clients with different requests, queue or log
requests, and support undoable operations.
25
Command Pattern Structure1
<<interface>>
Client Invoker Command
execute()
Receiver ConcreteCommand
action() state
execute() receiver.action();
26
Command Pattern Structure2
1: new ConcreteCommand(aReceiver)
2: storeCommand(aConcreteCommand)
3: execute()
4: action()
27
Command Pattern Structure3
28
Homework: Requirements
Statement
You’ve got an existing client class that use a vendor class
library.
After a while you found another vendor class library is
better, but the new vendor designed their interfaces
differently.
29