@@ -14,14 +14,14 @@ Action, Transaction
1414
1515## Intent
1616
17- Encapsulate a request as an object, thereby letting you parameterize clients with different
17+ Encapsulate a request as an object, thereby letting you parameterize clients with different
1818requests, queue or log requests, and support undoable operations.
1919
2020## Explanation
2121Real world example
2222
23- > There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one.
24- > The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses
23+ > There is a wizard casting spells on a goblin. The spells are executed on the goblin one by one.
24+ > The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses
2525> the spells one by one. Each spell here is a command object that can be undone.
2626
2727In plain words
@@ -30,8 +30,8 @@ In plain words
3030
3131Wikipedia says
3232
33- > In object-oriented programming, the command pattern is a behavioral design pattern in which an
34- > object is used to encapsulate all information needed to perform an action or trigger an event at
33+ > In object-oriented programming, the command pattern is a behavioral design pattern in which an
34+ > object is used to encapsulate all information needed to perform an action or trigger an event at
3535> a later time.
3636
3737** Programmatic Example**
@@ -48,27 +48,24 @@ public class Wizard {
4848
4949 public Wizard () {}
5050
51- public void castSpell (Command command , Target target ) {
52- LOGGER . info(" {} casts {} at {}" , this , command, target);
53- command. execute(target);
54- undoStack. offerLast(command);
51+ public void castSpell (Runnable runnable ) {
52+ runnable. run();
53+ undoStack. offerLast(runnable);
5554 }
5655
5756 public void undoLastSpell () {
5857 if (! undoStack. isEmpty()) {
5958 var previousSpell = undoStack. pollLast();
6059 redoStack. offerLast(previousSpell);
61- LOGGER . info(" {} undoes {}" , this , previousSpell);
62- previousSpell. undo();
60+ previousSpell. run();
6361 }
6462 }
6563
6664 public void redoLastSpell () {
6765 if (! redoStack. isEmpty()) {
6866 var previousSpell = redoStack. pollLast();
6967 undoStack. offerLast(previousSpell);
70- LOGGER . info(" {} redoes {}" , this , previousSpell);
71- previousSpell. redo();
68+ previousSpell. run();
7269 }
7370 }
7471
@@ -79,84 +76,7 @@ public class Wizard {
7976}
8077```
8178
82- Next we present the spell hierarchy.
83-
84- ``` java
85- public interface Command {
86-
87- void execute (Target target );
88-
89- void undo ();
90-
91- void redo ();
92-
93- String toString ();
94- }
95-
96- public class InvisibilitySpell implements Command {
97-
98- private Target target;
99-
100- @Override
101- public void execute (Target target ) {
102- target. setVisibility(Visibility . INVISIBLE );
103- this . target = target;
104- }
105-
106- @Override
107- public void undo () {
108- if (target != null ) {
109- target. setVisibility(Visibility . VISIBLE );
110- }
111- }
112-
113- @Override
114- public void redo () {
115- if (target != null ) {
116- target. setVisibility(Visibility . INVISIBLE );
117- }
118- }
119-
120- @Override
121- public String toString () {
122- return " Invisibility spell" ;
123- }
124- }
125-
126- public class ShrinkSpell implements Command {
127-
128- private Size oldSize;
129- private Target target;
130-
131- @Override
132- public void execute (Target target ) {
133- oldSize = target. getSize();
134- target. setSize(Size . SMALL );
135- this . target = target;
136- }
137-
138- @Override
139- public void undo () {
140- if (oldSize != null && target != null ) {
141- var temp = target. getSize();
142- target. setSize(oldSize);
143- oldSize = temp;
144- }
145- }
146-
147- @Override
148- public void redo () {
149- undo();
150- }
151-
152- @Override
153- public String toString () {
154- return " Shrink spell" ;
155- }
156- }
157- ```
158-
159- Finally, we have the goblin who's the target of the spells.
79+ Next, we have the goblin who's the target of the spells.
16080
16181``` java
16282public abstract class Target {
@@ -203,33 +123,73 @@ public class Goblin extends Target {
203123 return " Goblin" ;
204124 }
205125
126+ public void changeSize () {
127+ var oldSize = getSize() == Size . NORMAL ? Size . SMALL : Size . NORMAL ;
128+ setSize(oldSize);
129+ }
130+
131+ public void changeVisibility () {
132+ var visible = getVisibility() == Visibility . INVISIBLE
133+ ? Visibility . VISIBLE : Visibility . INVISIBLE ;
134+ setVisibility(visible);
135+ }
206136}
207137```
208138
139+ Finally we have the wizard in main function who casts spell
140+
141+ ``` java
142+ public static void main(String [] args) {
143+ var wizard = new Wizard ();
144+ var goblin = new Goblin ();
145+
146+ // casts shrink/unshrink spell
147+ wizard. castSpell(goblin:: changeSize);
148+
149+ // casts visible/invisible spell
150+ wizard. castSpell(goblin:: changeVisibility);
151+
152+ // undo and redo casts
153+ wizard. undoLastSpell();
154+ wizard. redoLastSpell();
155+ ```
156+
209157Here ' s the whole example in action.
210158
211159```java
212160var wizard = new Wizard();
213161var goblin = new Goblin();
162+
163+ goblin.printStatus();
164+ wizard.castSpell(goblin::changeSize);
214165goblin.printStatus();
215- wizard. castSpell(new ShrinkSpell (), goblin);
166+
167+ wizard.castSpell(goblin::changeVisibility);
216168goblin.printStatus();
217- wizard. castSpell(new InvisibilitySpell (), goblin);
169+
170+ wizard.undoLastSpell();
218171goblin.printStatus();
172+
219173wizard.undoLastSpell();
220174goblin.printStatus();
175+
176+ wizard.redoLastSpell();
177+ goblin.printStatus();
178+
179+ wizard.redoLastSpell();
180+ goblin.printStatus();
221181```
222182
223183Here' s the program output:
224184
225185```java
226- // Goblin, [size=normal] [visibility=visible]
227- // Wizard casts Shrink spell at Goblin
228- // Goblin, [size=small] [visibility=visible ]
229- // Wizard casts Invisibility spell at Goblin
230- // Goblin, [size=small ] [visibility=invisible ]
231- // Wizard undoes Invisibility spell
232- // Goblin, [size=small] [visibility=visible ]
186+ Goblin , [size= normal] [visibility= visible]
187+ Goblin , [size = small] [visibility = visible]
188+ Goblin , [size= small] [visibility= invisible ]
189+ Goblin , [size = small] [visibility = visible]
190+ Goblin , [size= normal ] [visibility= visible ]
191+ Goblin , [size = small] [visibility = visible]
192+ Goblin , [size= small] [visibility= invisible ]
233193```
234194
235195## Class diagram
@@ -240,26 +200,26 @@ Here's the program output:
240200
241201Use the Command pattern when you want to:
242202
243- * Parameterize objects by an action to perform. You can express such parameterization in a
244- procedural language with a callback function, that is, a function that's registered somewhere to be
203+ * Parameterize objects by an action to perform. You can express such parameterization in a
204+ procedural language with a callback function, that is, a function that' s registered somewhere to be
245205called at a later point. Commands are an object-oriented replacement for callbacks.
246- * Specify, queue, and execute requests at different times. A Command object can have a lifetime
247- independent of the original request. If the receiver of a request can be represented in an address
248- space-independent way, then you can transfer a command object for the request to a different process
206+ * Specify, queue, and execute requests at different times. A Command object can have a lifetime
207+ independent of the original request. If the receiver of a request can be represented in an address
208+ space-independent way, then you can transfer a command object for the request to a different process
249209and fulfill the request there.
250- * Support undo. The Command's execute operation can store state for reversing its effects in the
251- command itself. The Command interface must have an added un-execute operation that reverses the
252- effects of a previous call to execute. The executed commands are stored in a history list.
253- Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling
210+ * Support undo. The Command' s execute operation can store state for reversing its effects in the
211+ command itself. The Command interface must have an added un-execute operation that reverses the
212+ effects of a previous call to execute. The executed commands are stored in a history list.
213+ Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling
254214un-execute and execute, respectively.
255- * Support logging changes so that they can be reapplied in case of a system crash. By augmenting the
256- Command interface with load and store operations, you can keep a persistent log of changes.
257- Recovering from a crash involves reloading logged commands from disk and re-executing them with
215+ * Support logging changes so that they can be reapplied in case of a system crash. By augmenting the
216+ Command interface with load and store operations, you can keep a persistent log of changes.
217+ Recovering from a crash involves reloading logged commands from disk and re-executing them with
258218the execute operation.
259- * Structure a system around high-level operations build on primitive operations. Such a structure is
260- common in information systems that support transactions. A transaction encapsulates a set of changes
261- to data. The Command pattern offers a way to model transactions. Commands have a common interface,
262- letting you invoke all transactions the same way. The pattern also makes it easy to extend the
219+ * Structure a system around high-level operations build on primitive operations. Such a structure is
220+ common in information systems that support transactions. A transaction encapsulates a set of changes
221+ to data. The Command pattern offers a way to model transactions. Commands have a common interface,
222+ letting you invoke all transactions the same way. The pattern also makes it easy to extend the
263223system with new transactions.
264224
265225## Typical Use Case
0 commit comments