Asking for a review of my implementation of a command pattern. In a Editor, words can be entered and the entering of words can be undone.
General purpose Interface
public interface Command {
void execute();
}
The concrete write word command
// Command
public class WriteCommand implements Command {
private Editor editor;
private String word;
public WriteCommand(String w, Editor e) {
this.word = w;
this.editor = e;
}
public String getWord() {
return this.word;
}
public void execute() {
this.editor.addToWordList(this.getWord());
}
}
The undo command
public class UndoCommand implements Command {
private Editor editor;
public UndoCommand(Editor e) {
this.editor = e;
}
@Override
public void execute() {
editor.removeFromWordList();
}
}
The editor (i.e. receiver, i believe):
// Receiver
public class Editor {
private List<String> wordList;
public Editor() {
wordList = new ArrayList<>();
}
public void addToWordList(String w) {
this.wordList.add(w);
}
public void removeFromWordList() {
this.wordList.remove(this.wordList.size()-1);
}
List<String> getWordList() {
return this.wordList;
}
}
The invoker keeping the command queue:
public class Invoker {
private List<Command> undoList;
private List<Command> redoList;
public Invoker() {
undoList = new ArrayList<>();
redoList = new ArrayList<>();
}
public void executeCommand(Command c) {
undoList.add(c);
c.execute();
}
}
The client responsible for creating the commands:
public class Client {
public static void main(String[] args) {
Editor e = new Editor();
Invoker invoker = new Invoker();
invoker.executeCommand(new WriteCommand("Hello", e));
invoker.executeCommand(new WriteCommand("World", e));
System.out.println(e.getWordList());
invoker.executeCommand(new UndoCommand(e));
System.out.println(e.getWordList());
}
}
1 Answer 1
If this was a school exercise
It's a basic command pattern without any safety checks against programming errors. :) It would be a good idea to check that a word can not be removed from an empty list.
If this was a job interview assignment
While the code shows that you know how to code a command pattern it doesn't tell me if you understand why one would want to use it. Having WriteCommand and UndoCommand objects going around in isolation makes very little sense. And domain-wise, writing to a text editor with command objects is probably not something that I would do.
Instead put the command pattern into actual use by, for example, integrating it to the editor in the form of an undo/redo stack. Appending strings to the editor automatically create undo commands into the stack and performing the undo command executes the last command and adds a corresponding redo command into the redo stack.
Command
itself - it makes more sense to make it a parameter for theexecute
method. That's more flexible, and you would have less trouble e.g. serializing theCommand
instances that way. Of course, you should not put theUndoCommand
instances in theundoList
. But to me, this seems to be on the right track. \$\endgroup\$removeFromWordList
your undo maye be used to undo other changes but also to remove another word; your user may want to have a menu to undo "Hello".. (think of your browser's history, you can go back to teh last "n" entries) \$\endgroup\$Edit -> Undo
queue, for one. \$\endgroup\$