Skip to content

Commit db6ec3c

Browse files
committed
iluwatar#95 Updated and clarified Command pattern example
1 parent fb446c2 commit db6ec3c

File tree

9 files changed

+223
-236
lines changed

9 files changed

+223
-236
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ A programming idiom is a means of expressing a recurring construct in one or mor
299299
## <a name="command">Command</a> [&#8593;](#list-of-design-patterns)
300300
**Intent:** Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
301301

302-
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/command/etc/command_1.png "Command")
302+
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/command/etc/command.png "Command")
303303

304304
**Applicability:** Use the Command pattern when you want to
305305

command/etc/command.png

-11.4 KB
Loading

command/etc/command.ucls

Lines changed: 34 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
44
<class id="1" language="java" name="com.iluwatar.command.ShrinkSpell" project="command"
55
file="/command/src/main/java/com/iluwatar/command/ShrinkSpell.java" binary="false" corner="BOTTOM_RIGHT">
6-
<position height="160" width="141" x="-171" y="634"/>
6+
<position height="178" width="141" x="-30" y="681"/>
77
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
88
sort-features="false" accessors="true" visibility="true">
99
<attributes public="true" package="true" protected="true" private="true" static="true"/>
@@ -12,7 +12,7 @@
1212
</class>
1313
<class id="2" language="java" name="com.iluwatar.command.Goblin" project="command"
1414
file="/command/src/main/java/com/iluwatar/command/Goblin.java" binary="false" corner="BOTTOM_RIGHT">
15-
<position height="106" width="138" x="13" y="1069"/>
15+
<position height="-1" width="-1" x="129" y="1223"/>
1616
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
1717
sort-features="false" accessors="true" visibility="true">
1818
<attributes public="true" package="true" protected="true" private="true" static="true"/>
@@ -21,7 +21,7 @@
2121
</class>
2222
<class id="3" language="java" name="com.iluwatar.command.Wizard" project="command"
2323
file="/command/src/main/java/com/iluwatar/command/Wizard.java" binary="false" corner="BOTTOM_RIGHT">
24-
<position height="160" width="212" x="91" y="235"/>
24+
<position height="-1" width="-1" x="129" y="362"/>
2525
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
2626
sort-features="false" accessors="true" visibility="true">
2727
<attributes public="true" package="true" protected="true" private="true" static="true"/>
@@ -30,7 +30,7 @@
3030
</class>
3131
<class id="4" language="java" name="com.iluwatar.command.Command" project="command"
3232
file="/command/src/main/java/com/iluwatar/command/Command.java" binary="false" corner="BOTTOM_RIGHT">
33-
<position height="159" width="142" x="9" y="435"/>
33+
<position height="-1" width="-1" x="129" y="561"/>
3434
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
3535
sort-features="false" accessors="true" visibility="true">
3636
<attributes public="true" package="true" protected="true" private="true" static="true"/>
@@ -39,66 +39,58 @@
3939
</class>
4040
<class id="5" language="java" name="com.iluwatar.command.InvisibilitySpell" project="command"
4141
file="/command/src/main/java/com/iluwatar/command/InvisibilitySpell.java" binary="false" corner="BOTTOM_RIGHT">
42-
<position height="160" width="141" x="10" y="634"/>
42+
<position height="160" width="141" x="151" y="681"/>
4343
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
4444
sort-features="false" accessors="true" visibility="true">
4545
<attributes public="true" package="true" protected="true" private="true" static="true"/>
4646
<operations public="true" package="true" protected="true" private="true" static="true"/>
4747
</display>
4848
</class>
49-
<enumeration id="6" language="java" name="com.iluwatar.command.Visibility" project="command"
50-
file="/command/src/main/java/com/iluwatar/command/Visibility.java" binary="false" corner="BOTTOM_RIGHT">
51-
<position height="178" width="157" x="191" y="1069"/>
52-
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
53-
sort-features="false" accessors="true" visibility="true">
54-
<attributes public="true" package="true" protected="true" private="true" static="true"/>
55-
<operations public="true" package="true" protected="true" private="true" static="true"/>
56-
</display>
57-
</enumeration>
58-
<enumeration id="7" language="java" name="com.iluwatar.command.Size" project="command"
59-
file="/command/src/main/java/com/iluwatar/command/Size.java" binary="false" corner="BOTTOM_RIGHT">
60-
<position height="196" width="144" x="-171" y="1069"/>
61-
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
62-
sort-features="false" accessors="true" visibility="true">
63-
<attributes public="true" package="true" protected="true" private="true" static="true"/>
64-
<operations public="true" package="true" protected="true" private="true" static="true"/>
65-
</display>
66-
</enumeration>
67-
<class id="8" language="java" name="com.iluwatar.command.Target" project="command"
49+
<class id="6" language="java" name="com.iluwatar.command.Target" project="command"
6850
file="/command/src/main/java/com/iluwatar/command/Target.java" binary="false" corner="BOTTOM_RIGHT">
69-
<position height="195" width="176" x="13" y="834"/>
51+
<position height="-1" width="-1" x="129" y="1014"/>
7052
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
7153
sort-features="false" accessors="true" visibility="true">
7254
<attributes public="true" package="true" protected="true" private="true" static="true"/>
7355
<operations public="true" package="true" protected="true" private="true" static="true"/>
7456
</display>
7557
</class>
76-
<association id="9">
58+
<association id="7">
59+
<end type="SOURCE" refId="3" navigable="false">
60+
<attribute id="8" name="redoStack">
61+
<position height="20" width="67" x="140" y="451"/>
62+
</attribute>
63+
<multiplicity id="9" minimum="0" maximum="2147483647">
64+
<position height="18" width="25" x="221" y="452"/>
65+
</multiplicity>
66+
</end>
67+
<end type="TARGET" refId="4" navigable="true"/>
68+
<display labels="true" multiplicity="true"/>
69+
</association>
70+
<generalization id="10">
71+
<end type="SOURCE" refId="2"/>
72+
<end type="TARGET" refId="6"/>
73+
</generalization>
74+
<association id="11">
7775
<end type="SOURCE" refId="1" navigable="false">
78-
<attribute id="10" name="target"/>
79-
<multiplicity id="11" minimum="0" maximum="1"/>
76+
<attribute id="12" name="target"/>
77+
<multiplicity id="13" minimum="0" maximum="1"/>
8078
</end>
81-
<end type="TARGET" refId="8" navigable="true"/>
79+
<end type="TARGET" refId="6" navigable="true"/>
8280
<display labels="true" multiplicity="true"/>
8381
</association>
84-
<generalization id="12">
82+
<generalization id="14">
8583
<end type="SOURCE" refId="1"/>
8684
<end type="TARGET" refId="4"/>
8785
</generalization>
88-
<generalization id="13">
89-
<bendpoint x="181" y="435"/>
90-
<bendpoint x="181" y="634"/>
91-
<end type="SOURCE" refId="3"/>
92-
<end type="TARGET" refId="8"/>
93-
</generalization>
94-
<generalization id="14">
95-
<end type="SOURCE" refId="2"/>
96-
<end type="TARGET" refId="8"/>
97-
</generalization>
9886
<association id="15">
9987
<end type="SOURCE" refId="3" navigable="false">
100-
<attribute id="16" name="undoStack"/>
101-
<multiplicity id="17" minimum="0" maximum="2147483647"/>
88+
<attribute id="16" name="undoStack">
89+
<position height="20" width="70" x="-17" y="451"/>
90+
</attribute>
91+
<multiplicity id="17" minimum="0" maximum="2147483647">
92+
<position height="18" width="25" x="60" y="452"/>
93+
</multiplicity>
10294
</end>
10395
<end type="TARGET" refId="4" navigable="true"/>
10496
<display labels="true" multiplicity="true"/>
@@ -112,42 +104,9 @@
112104
<attribute id="20" name="target"/>
113105
<multiplicity id="21" minimum="0" maximum="1"/>
114106
</end>
115-
<end type="TARGET" refId="8" navigable="true"/>
116-
<display labels="true" multiplicity="true"/>
117-
</association>
118-
<association id="22">
119-
<end type="SOURCE" refId="8" navigable="false">
120-
<attribute id="23" name="visibility"/>
121-
<multiplicity id="24" minimum="0" maximum="1"/>
122-
</end>
123107
<end type="TARGET" refId="6" navigable="true"/>
124108
<display labels="true" multiplicity="true"/>
125109
</association>
126-
<association id="25">
127-
<end type="SOURCE" refId="8" navigable="false">
128-
<attribute id="26" name="size"/>
129-
<multiplicity id="27" minimum="0" maximum="1"/>
130-
</end>
131-
<end type="TARGET" refId="7" navigable="true"/>
132-
<display labels="true" multiplicity="true"/>
133-
</association>
134-
<association id="28">
135-
<end type="SOURCE" refId="3" navigable="false">
136-
<attribute id="29" name="redoStack"/>
137-
<multiplicity id="30" minimum="0" maximum="2147483647"/>
138-
</end>
139-
<end type="TARGET" refId="4" navigable="true"/>
140-
<display labels="true" multiplicity="true"/>
141-
</association>
142-
<association id="31">
143-
<bendpoint x="-162" y="834"/>
144-
<end type="SOURCE" refId="1" navigable="false">
145-
<attribute id="32" name="oldSize"/>
146-
<multiplicity id="33" minimum="0" maximum="1"/>
147-
</end>
148-
<end type="TARGET" refId="7" navigable="true"/>
149-
<display labels="true" multiplicity="true"/>
150-
</association>
151110
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
152111
sort-features="false" accessors="true" visibility="true">
153112
<attributes public="true" package="true" protected="true" private="true" static="true"/>

command/etc/command_1.png

-66 KB
Binary file not shown.
Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,47 @@
1-
package com.iluwatar.command;
2-
3-
/**
4-
*
5-
* In Command pattern actions are objects that can be executed and undone.
6-
*
7-
* In this example the commands are the spells cast by the wizard on the goblin.
8-
*
9-
*/
10-
public class App {
11-
12-
public static void main(String[] args) {
13-
Wizard wizard = new Wizard();
14-
Goblin goblin = new Goblin();
15-
16-
goblin.printStatus();
17-
18-
wizard.castSpell(new ShrinkSpell(), goblin);
19-
goblin.printStatus();
20-
21-
wizard.castSpell(new InvisibilitySpell(), goblin);
22-
goblin.printStatus();
23-
24-
wizard.undoLastSpell();
25-
goblin.printStatus();
26-
27-
wizard.undoLastSpell();
28-
goblin.printStatus();
29-
30-
wizard.redoLastSpell();
31-
goblin.printStatus();
32-
33-
wizard.redoLastSpell();
34-
goblin.printStatus();
35-
}
36-
}
1+
package com.iluwatar.command;
2+
3+
/**
4+
*
5+
* In Command pattern actions are objects that can be executed and undone.
6+
*
7+
* Four terms always associated with the command pattern are command, receiver, invoker and client. A command
8+
* object (spell) knows about receiver (target) and invokes a method of the receiver. Values for parameters of
9+
* the receiver method are stored in the command. The receiver then does the work. An invoker object (wizard)
10+
* knows how to execute a command, and optionally does bookkeeping about the command execution. The invoker
11+
* does not know anything about a concrete command, it knows only about command interface. Both an invoker object
12+
* and several command objects are held by a client object (app). The client decides which commands to execute at
13+
* which points. To execute a command, it passes the command object to the invoker object.
14+
*
15+
* In other words, in this example the wizard casts spells on the goblin. The wizard keeps track of the previous
16+
* spells cast, so it is easy to undo them. In addition, the wizard keeps track of the spells undone, so they
17+
* can be redone.
18+
*
19+
*
20+
*/
21+
public class App {
22+
23+
public static void main(String[] args) {
24+
Wizard wizard = new Wizard();
25+
Goblin goblin = new Goblin();
26+
27+
goblin.printStatus();
28+
29+
wizard.castSpell(new ShrinkSpell(), goblin);
30+
goblin.printStatus();
31+
32+
wizard.castSpell(new InvisibilitySpell(), goblin);
33+
goblin.printStatus();
34+
35+
wizard.undoLastSpell();
36+
goblin.printStatus();
37+
38+
wizard.undoLastSpell();
39+
goblin.printStatus();
40+
41+
wizard.redoLastSpell();
42+
goblin.printStatus();
43+
44+
wizard.redoLastSpell();
45+
goblin.printStatus();
46+
}
47+
}
Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
package com.iluwatar.command;
2-
3-
public class Goblin extends Target {
4-
5-
public Goblin() {
6-
setSize(Size.NORMAL);
7-
setVisibility(Visibility.VISIBLE);
8-
}
9-
10-
@Override
11-
public String toString() {
12-
return "Goblin";
13-
}
14-
15-
}
1+
package com.iluwatar.command;
2+
3+
/**
4+
*
5+
* Goblin is the target of the spells
6+
*
7+
*/
8+
public class Goblin extends Target {
9+
10+
public Goblin() {
11+
setSize(Size.NORMAL);
12+
setVisibility(Visibility.VISIBLE);
13+
}
14+
15+
@Override
16+
public String toString() {
17+
return "Goblin";
18+
}
19+
20+
}
Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
1-
package com.iluwatar.command;
2-
3-
public class InvisibilitySpell extends Command {
4-
5-
private Target target;
6-
7-
@Override
8-
public void execute(Target target) {
9-
target.setVisibility(Visibility.INVISIBLE);
10-
this.target = target;
11-
}
12-
13-
@Override
14-
public void undo() {
15-
if (target != null) {
16-
target.setVisibility(Visibility.VISIBLE);
17-
}
18-
}
19-
20-
@Override
21-
public void redo() {
22-
if (target != null) {
23-
target.setVisibility(Visibility.INVISIBLE);
24-
}
25-
}
26-
27-
@Override
28-
public String toString() {
29-
return "Invisibility spell";
30-
}
31-
}
1+
package com.iluwatar.command;
2+
3+
/**
4+
*
5+
* InvisibilitySpell is a concrete command
6+
*
7+
*/
8+
public class InvisibilitySpell extends Command {
9+
10+
private Target target;
11+
12+
@Override
13+
public void execute(Target target) {
14+
target.setVisibility(Visibility.INVISIBLE);
15+
this.target = target;
16+
}
17+
18+
@Override
19+
public void undo() {
20+
if (target != null) {
21+
target.setVisibility(Visibility.VISIBLE);
22+
}
23+
}
24+
25+
@Override
26+
public void redo() {
27+
if (target != null) {
28+
target.setVisibility(Visibility.INVISIBLE);
29+
}
30+
}
31+
32+
@Override
33+
public String toString() {
34+
return "Invisibility spell";
35+
}
36+
}

0 commit comments

Comments
 (0)