Encapsulate a request as an object. This lets you parameterize clients with different requests, queue or log requests, and support undoable operations.
// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// A text editing canvas providing complete copy, paste, and multi-level
// action undo/redo tracking.
//
// WHERE THE COMMAND FITS IN:
// Command is the Command interface declaring execute(). CopyCommand is a
// Concrete Command. Editor represents the Receiver. CommandInvoker triggers
// actions.
// ────────────────────────────────────────────────────────────────────────────
import java.util.ArrayDeque;
import java.util.Deque;
// --- Command interface ---
interface Command {
void execute();
void undo();
}
// --- Receiver ---
class TextEditor {
private final StringBuilder content = new StringBuilder();
public void append(String text) { content.append(text); }
public void deleteLast(int length) {
int start = Math.max(0, content.length() - length);
content.delete(start, content.length());
}
public String getContent() { return content.toString(); }
}
// --- Concrete commands ---
class AppendCommand implements Command {
private final TextEditor editor;
private final String text;
public AppendCommand(TextEditor editor, String text) {
this.editor = editor;
this.text = text;
}
public void execute() {
editor.append(text);
}
public void undo() {
editor.deleteLast(text.length());
}
}
// --- Invoker (with undo stack) ---
class CommandHistory {
private final Deque<Command> history = new ArrayDeque<>();
private final Deque<Command> redoStack = new ArrayDeque<>();
public void execute(Command cmd) {
cmd.execute();
history.push(cmd);
redoStack.clear();
}
public void undo() {
if (!history.isEmpty()) {
Command cmd = history.pop();
cmd.undo();
redoStack.push(cmd);
}
}
public void redo() {
if (!redoStack.isEmpty()) {
Command cmd = redoStack.pop();
cmd.execute();
history.push(cmd);
}
}
}
public class Main {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
CommandHistory history = new CommandHistory();
history.execute(new AppendCommand(editor, "Hello "));
history.execute(new AppendCommand(editor, "World!"));
System.out.println("After: " + editor.getContent()); // Hello World!
history.undo();
System.out.println("After undo: " + editor.getContent()); // Hello
history.redo();
System.out.println("After redo: " + editor.getContent()); // Hello World!
}
}