diff --git a/README.md b/README.md index d7563bd11..59312ea84 100644 --- a/README.md +++ b/README.md @@ -299,7 +299,7 @@ A programming idiom is a means of expressing a recurring construct in one or mor ## Command [↑](#list-of-design-patterns) **Intent:** Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. -![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/command/etc/command_1.png "Command") +![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/command/etc/command.png "Command") **Applicability:** Use the Command pattern when you want to diff --git a/command/etc/command.png b/command/etc/command.png index e234265bf..81b47d6d0 100644 Binary files a/command/etc/command.png and b/command/etc/command.png differ diff --git a/command/etc/command.ucls b/command/etc/command.ucls index 69f0a340e..f0e0857d2 100644 --- a/command/etc/command.ucls +++ b/command/etc/command.ucls @@ -3,7 +3,7 @@ realizations="true" associations="true" dependencies="false" nesting-relationships="true"> - + @@ -12,7 +12,7 @@ - + @@ -21,7 +21,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -39,66 +39,58 @@ - + - - - - - - - - - - - - - - - - + - - - - + + + + + + + + - + - + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + @@ -112,42 +104,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/command/etc/command_1.png b/command/etc/command_1.png deleted file mode 100644 index e2e7b9e0e..000000000 Binary files a/command/etc/command_1.png and /dev/null differ diff --git a/command/src/main/java/com/iluwatar/command/App.java b/command/src/main/java/com/iluwatar/command/App.java index 0e47b4ce1..6d9df821c 100644 --- a/command/src/main/java/com/iluwatar/command/App.java +++ b/command/src/main/java/com/iluwatar/command/App.java @@ -1,36 +1,47 @@ -package com.iluwatar.command; - -/** - * - * In Command pattern actions are objects that can be executed and undone. - * - * In this example the commands are the spells cast by the wizard on the goblin. - * - */ -public class App { - - public static void main(String[] args) { - Wizard wizard = new Wizard(); - Goblin goblin = new Goblin(); - - goblin.printStatus(); - - wizard.castSpell(new ShrinkSpell(), goblin); - goblin.printStatus(); - - wizard.castSpell(new InvisibilitySpell(), goblin); - goblin.printStatus(); - - wizard.undoLastSpell(); - goblin.printStatus(); - - wizard.undoLastSpell(); - goblin.printStatus(); - - wizard.redoLastSpell(); - goblin.printStatus(); - - wizard.redoLastSpell(); - goblin.printStatus(); - } -} +package com.iluwatar.command; + +/** + * + * In Command pattern actions are objects that can be executed and undone. + * + * Four terms always associated with the command pattern are command, receiver, invoker and client. A command + * object (spell) knows about receiver (target) and invokes a method of the receiver. Values for parameters of + * the receiver method are stored in the command. The receiver then does the work. An invoker object (wizard) + * knows how to execute a command, and optionally does bookkeeping about the command execution. The invoker + * does not know anything about a concrete command, it knows only about command interface. Both an invoker object + * and several command objects are held by a client object (app). The client decides which commands to execute at + * which points. To execute a command, it passes the command object to the invoker object. + * + * In other words, in this example the wizard casts spells on the goblin. The wizard keeps track of the previous + * spells cast, so it is easy to undo them. In addition, the wizard keeps track of the spells undone, so they + * can be redone. + * + * + */ +public class App { + + public static void main(String[] args) { + Wizard wizard = new Wizard(); + Goblin goblin = new Goblin(); + + goblin.printStatus(); + + wizard.castSpell(new ShrinkSpell(), goblin); + goblin.printStatus(); + + wizard.castSpell(new InvisibilitySpell(), goblin); + goblin.printStatus(); + + wizard.undoLastSpell(); + goblin.printStatus(); + + wizard.undoLastSpell(); + goblin.printStatus(); + + wizard.redoLastSpell(); + goblin.printStatus(); + + wizard.redoLastSpell(); + goblin.printStatus(); + } +} diff --git a/command/src/main/java/com/iluwatar/command/Goblin.java b/command/src/main/java/com/iluwatar/command/Goblin.java index 16da93819..7d0804b0c 100644 --- a/command/src/main/java/com/iluwatar/command/Goblin.java +++ b/command/src/main/java/com/iluwatar/command/Goblin.java @@ -1,15 +1,20 @@ -package com.iluwatar.command; - -public class Goblin extends Target { - - public Goblin() { - setSize(Size.NORMAL); - setVisibility(Visibility.VISIBLE); - } - - @Override - public String toString() { - return "Goblin"; - } - -} +package com.iluwatar.command; + +/** + * + * Goblin is the target of the spells + * + */ +public class Goblin extends Target { + + public Goblin() { + setSize(Size.NORMAL); + setVisibility(Visibility.VISIBLE); + } + + @Override + public String toString() { + return "Goblin"; + } + +} diff --git a/command/src/main/java/com/iluwatar/command/InvisibilitySpell.java b/command/src/main/java/com/iluwatar/command/InvisibilitySpell.java index 858bd9537..b72c34cc2 100644 --- a/command/src/main/java/com/iluwatar/command/InvisibilitySpell.java +++ b/command/src/main/java/com/iluwatar/command/InvisibilitySpell.java @@ -1,31 +1,36 @@ -package com.iluwatar.command; - -public class InvisibilitySpell extends Command { - - private Target target; - - @Override - public void execute(Target target) { - target.setVisibility(Visibility.INVISIBLE); - this.target = target; - } - - @Override - public void undo() { - if (target != null) { - target.setVisibility(Visibility.VISIBLE); - } - } - - @Override - public void redo() { - if (target != null) { - target.setVisibility(Visibility.INVISIBLE); - } - } - - @Override - public String toString() { - return "Invisibility spell"; - } -} +package com.iluwatar.command; + +/** + * + * InvisibilitySpell is a concrete command + * + */ +public class InvisibilitySpell extends Command { + + private Target target; + + @Override + public void execute(Target target) { + target.setVisibility(Visibility.INVISIBLE); + this.target = target; + } + + @Override + public void undo() { + if (target != null) { + target.setVisibility(Visibility.VISIBLE); + } + } + + @Override + public void redo() { + if (target != null) { + target.setVisibility(Visibility.INVISIBLE); + } + } + + @Override + public String toString() { + return "Invisibility spell"; + } +} diff --git a/command/src/main/java/com/iluwatar/command/ShrinkSpell.java b/command/src/main/java/com/iluwatar/command/ShrinkSpell.java index 6f8a9bb37..f36438082 100644 --- a/command/src/main/java/com/iluwatar/command/ShrinkSpell.java +++ b/command/src/main/java/com/iluwatar/command/ShrinkSpell.java @@ -1,33 +1,38 @@ -package com.iluwatar.command; - -public class ShrinkSpell extends Command { - - private Size oldSize; - private Target target; - - @Override - public void execute(Target target) { - oldSize = target.getSize(); - target.setSize(Size.SMALL); - this.target = target; - } - - @Override - public void undo() { - if (oldSize != null && target != null) { - Size temp = target.getSize(); - target.setSize(oldSize); - oldSize = temp; - } - } - - @Override - public void redo() { - undo(); - } - - @Override - public String toString() { - return "Shrink spell"; - } -} +package com.iluwatar.command; + +/** + * + * ShrinkSpell is a concrete command + * + */ +public class ShrinkSpell extends Command { + + private Size oldSize; + private Target target; + + @Override + public void execute(Target target) { + oldSize = target.getSize(); + target.setSize(Size.SMALL); + this.target = target; + } + + @Override + public void undo() { + if (oldSize != null && target != null) { + Size temp = target.getSize(); + target.setSize(oldSize); + oldSize = temp; + } + } + + @Override + public void redo() { + undo(); + } + + @Override + public String toString() { + return "Shrink spell"; + } +} diff --git a/command/src/main/java/com/iluwatar/command/Wizard.java b/command/src/main/java/com/iluwatar/command/Wizard.java index 05f33d9be..995b4441a 100644 --- a/command/src/main/java/com/iluwatar/command/Wizard.java +++ b/command/src/main/java/com/iluwatar/command/Wizard.java @@ -1,45 +1,47 @@ -package com.iluwatar.command; - -import java.util.Deque; -import java.util.LinkedList; - -public class Wizard extends Target { - - private Deque undoStack = new LinkedList<>(); - private Deque redoStack = new LinkedList<>(); - - public Wizard() { - setSize(Size.NORMAL); - setVisibility(Visibility.VISIBLE); - } - - public void castSpell(Command command, Target target) { - System.out.println(this + " casts " + command + " at " + target); - command.execute(target); - undoStack.offerLast(command); - } - - public void undoLastSpell() { - if (!undoStack.isEmpty()) { - Command previousSpell = undoStack.pollLast(); - redoStack.offerLast(previousSpell); - System.out.println(this + " undoes " + previousSpell); - previousSpell.undo(); - } - } - - public void redoLastSpell() { - if (!redoStack.isEmpty()) { - Command previousSpell = redoStack.pollLast(); - undoStack.offerLast(previousSpell); - System.out.println(this + " redoes " + previousSpell); - previousSpell.redo(); - } - } - - @Override - public String toString() { - return "Wizard"; - } - -} +package com.iluwatar.command; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * + * Wizard is the invoker of the commands + * + */ +public class Wizard { + + private Deque undoStack = new LinkedList<>(); + private Deque redoStack = new LinkedList<>(); + + public Wizard() { + } + + public void castSpell(Command command, Target target) { + System.out.println(this + " casts " + command + " at " + target); + command.execute(target); + undoStack.offerLast(command); + } + + public void undoLastSpell() { + if (!undoStack.isEmpty()) { + Command previousSpell = undoStack.pollLast(); + redoStack.offerLast(previousSpell); + System.out.println(this + " undoes " + previousSpell); + previousSpell.undo(); + } + } + + public void redoLastSpell() { + if (!redoStack.isEmpty()) { + Command previousSpell = redoStack.pollLast(); + undoStack.offerLast(previousSpell); + System.out.println(this + " redoes " + previousSpell); + previousSpell.redo(); + } + } + + @Override + public String toString() { + return "Wizard"; + } +}