Behavioral PatternsCommand PatternMedium⏱️ ~3 min

Command Pattern: Text Editor Application

Domain: Text Editor with Undo/Redo

We will design a text editor supporting bold, italic, and delete operations with full undo/redo capability. Each formatting action becomes a command that can be reversed.

«interface»
EditorCommand
+ execute(): void
+ undo(): void
BoldCommand
- editor: TextEditor
- start: int
- end: int
+ execute(): void
+ undo(): void
DeleteCommand
- editor: TextEditor
- position: int
- deletedText: String
+ execute(): void
+ undo(): void
ItalicCommand
- editor: TextEditor
- start: int
- end: int
+ execute(): void
+ undo(): void
TextEditor
- content: String
+ applyBold(s,e): void
+ removeBold(s,e): void
+ deleteText(pos): String
+ insertText(pos,t): void
CommandHistory
- undoStack: Stack
- redoStack: Stack
+ execute(cmd): void
+ undo(): void
+ redo(): void

Design Decisions

State Storage: DeleteCommand stores deletedText so undo can restore it. BoldCommand stores start and end positions to reverse formatting. Each command captures whatever state is needed to reverse itself.

CommandHistory as Invoker: The CommandHistory class acts as invoker and maintains undo/redo stacks. When execute(cmd) is called, it executes the command, pushes it to undoStack, and clears redoStack. When undo() is called, it pops from undoStack, calls cmd.undo(), and pushes to redoStack. This centralized history management is cleaner than scattered undo logic.

TextEditor as Receiver: The TextEditor contains the actual document manipulation logic. It knows nothing about commands. Methods like applyBold() and deleteText() are reusable whether called from commands or elsewhere.

Execution Example

First, user selects text from position 5 to 10 and clicks the Bold button. Second, UI creates BoldCommand(editor, 5, 10) and passes it to history.execute(boldCmd). Third, CommandHistory calls boldCmd.execute(), which calls editor.applyBold(5, 10). Fourth, CommandHistory pushes boldCmd onto undoStack. Later, if user presses Ctrl+Z, CommandHistory pops boldCmd, calls boldCmd.undo(), which calls editor.removeBold(5, 10), and pushes boldCmd to redoStack. If user performs a new action, redoStack is cleared because redo is no longer valid after a new operation.

Interview Tip: Discuss how macro recording extends this design. A MacroCommand would hold a list of commands and execute/undo them all in sequence, demonstrating the Composite Pattern combined with Command Pattern.
💡 Key Takeaways
Each formatting operation becomes a separate command class
Commands store state needed for undo (deleted text, positions, previous values)
CommandHistory manages undo/redo stacks and clears redo on new actions
TextEditor (Receiver) remains independent and reusable without command knowledge
UI elements create commands and pass them to CommandHistory for execution
📌 Examples
1BoldCommand stores selection range to unbold on undo
2DeleteCommand stores deleted text to reinsert on undo
3MacroCommand combines multiple commands for complex operations
← Back to Command Pattern Overview