Download as pdf or txt
Download as pdf or txt
You are on page 1of 29

Command Pattern

Shin-Jie Lee (李信杰)


Associate Professor
Computer and Network Center
Department of CSIE
National Cheng Kung University
Design Aspect of Command

When and how a request is fulfilled

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

Shin-Jie Lee (李信杰)


Assistant Professor
Computer and Network Center
Department of CSIE
National Cheng Kung University
Requirements Statement1
The remote control can control a stereo remotely.
While a stereo is switched on by the remote
control, the CD and volume will be set at the same
time.
{ RemoteControl Stereo
if (!stereo.isOn()) {
stereo.on(); on()
stereo.setCD(); Stereo stereo
setCD()
stereo.setVolume();
stereoSwitch() setVolume()
}
isOn(): boolean
}

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
}
}

Problem: The remote control object is subject to be


modified once the set of the actions on a specific
receiver (stereo and light) is changed.

8
Design Process for Change

Design Principle: Encapsulate what


The code that changes has been varies.
encapsulated as a class?

Need abstraction?
Act-1: Encapsulate
No What Varies, methods No
and its corresponding
attributes Need composition?
Yes Yes

Act-2: Abstract Common Behaviors No


(with a same signature) into Interfaces
or Abstract Classes Yes

Design Principle: Program to an


interface, not an implementation.

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

1.2 Encapsulate a StereoCommand


{
if (!stereo.isOn()) {
method into a Stereo stereo
stereo.on();
stereo.setCD();
RemoteControl
concrete class execute() }
stereo.setVolume();

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

execute() 2.1 Abstract common


behaviors with a same
signature into interface
through inheritance

StereoOnCommand LightOnCommand

Stereo stereo Light light

execute() execute()

11
Act-3: Compose Abstract Behaviors

3.1 Compose behaviors of an


interface
RemoteControl <<interface>>
Command
Command cmd[]
execute()
setCommand(int index, Command cmd)
{
doCommand(int index)
cmd[index].execute();
}

Light Stereo StereoOnCommand LightOnCommand

on() on() Stereo stereo Light light


off() setCD()
isOn(): boolean setVolume() execute() execute()
isOn(): boolean

12
Refactored Design after Design Process

RemoteControl <<interface>>
Command
Command cmd[]
execute()
setCommand(int index, Command cmd)
{
doCommand(int index)
cmd[index].execute();
}

Light Stereo StereoOnCommand LightOnCommand

on() on() Stereo stereo Light light


off() setCD()
isOn(): boolean setVolume() execute() execute()
isOn(): boolean

13
Cut, Copy, Paste
on a Document

Shin-Jie Lee (李信杰)


Assistant Professor
Computer and Network Center
Department of CSIE
National Cheng Kung University
Requirements Statement1
An editor application carries 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();

CutMenuItem PasteMenuItem CopyMenuItem



doc.cut(); clicked() clicked() clicked()

Document …
doc.paste();
cut()
copy()
paste()

16
Initial Design

doc
Editor EditMenu * <<interface>>
MenuItem
clicked()

CutMenuItem PasteMenuItem CopyMenuItem



doc.cut(); clicked() clicked() clicked()

… …
doc.paste(); doc.copy();
Document
cut()
copy()
paste()

17
Problems with Initial Design

doc <<interface>>
Editor EditMenu * MenuItem
clicked()

CutMenuItem PasteMenuItem CopyMenuItem



doc.cut(); clicked() clicked() 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

Design Principle: Encapsulate what


The code that changes has been varies.
encapsulated as a class?

Need abstraction?
Act-1: Encapsulate
No What Varies, methods No
and its corresponding
attributes Need composition?
Yes Yes

Act-2: Abstract Common Behaviors No


(with a same signature) into Interfaces
or Abstract Classes Yes

Design Principle: Program to an


interface, not an implementation.

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()

CutMenuItem PasteMenuItem CopyMenuItem


1.2 Encapsulate a
clicked() clicked() clicked()
method into a
concrete class CutCommand PasteCommand CopyCommand
… doc doc doc
doc.cut(); execute()
execute() execute()
Document …
cut() doc.paste(); …
copy() doc.copy();
paste()

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

CutCommand PasteCommand CopyCommand


… doc doc doc
doc.cut(); execute() execute() execute() …
doc.copy();

Same signature with


different bodies

21
Act-3: Compose Abstract Behaviors

3.1 Compose behaviors of an


abstract class
doc command
Editor EditMenu MenuItem * Command
clicked() doc
… execute()
Change to abstract class doc.cut();

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

Receiver Client ConcreteCommand Invoker

1: new ConcreteCommand(aReceiver)

2: storeCommand(aConcreteCommand)

3: execute()
4: action()

27
Command Pattern Structure3

Instantiation Use Termination

Invoker keeps a Command reference, and then


Command X X
delegate to it while Invoker is requested.

Client creates a ConcreteCommand with a Receiver


ConcreteCommand
as a parameter, and store it to an Invoker.
will be terminated
Concrete
Client while the Invoker
Command The Invoker delegates the request to the
doesn’t need it
ConcreteCommand, and it uses the Receiver to
anymore.
complete the request.
Invoker holds a Command reference from Client.
Invoker Don’t Care Don’t Care
While Invoker is invoked, it delegates to Command.
Receiver is sent to ConcreteCommand as a
reference by Client.
Receiver Don’t Care Don’t Care
ConcreteCommand completes its request by using
Receiver.

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

You might also like