🧩 Command Pattern
✅ Intent
- Represent each user action as a command object that can be executed, undone, and redone
- Encapsulate operations to enable flexible undo/redo and history tracking
✅ Motivation
- Ideal for implementing Undo/Redo functionality in text editors, GUIs, and batch operations
- Allows you to log, test, or replay operations individually
✅ When to Use
- In systems like text editors, forms, batch processors, or GUI components
- When you want to separate the "action" from the "receiver" and support reversible operations
✅ Code Example
- TypeScript
- PHP
- Python
// コマンドインターフェース
interface Command {
execute(): void;
undo(): void;
}
// 受信者(対象クラス)
class TextEditor {
private content = "";
add(text: string) {
this.content += text;
}
remove(length: number) {
this.content = this.content.slice(0, -length);
}
getContent(): string {
return this.content;
}
}
// コマンド実装
class TypeCommand implements Command {
constructor(private editor: TextEditor, private text: string) {}
execute(): void {
this.editor.add(this.text);
}
undo(): void {
this.editor.remove(this.text.length);
}
}
// 利用例
const editor = new TextEditor();
const history: Command[] = [];
const cmd1 = new TypeCommand(editor, "Hello ");
cmd1.execute();
history.push(cmd1);
const cmd2 = new TypeCommand(editor, "World");
cmd2.execute();
history.push(cmd2);
console.log(editor.getContent()); // Hello World
// Undo(巻き戻し)
const last = history.pop();
last?.undo();
console.log(editor.getContent()); // Hello
<?php
interface Command {
public function execute(): void;
public function undo(): void;
}
class TextEditor {
private string $content = "";
public function add(string $text): void {
$this->content .= $text;
}
public function remove(int $length): void {
$this->content = substr($this->content, 0, -$length);
}
public function getContent(): string {
return $this->content;
}
}
class TypeCommand implements Command {
public function __construct(private TextEditor $editor, private string $text) {}
public function execute(): void {
$this->editor->add($this->text);
}
public function undo(): void {
$this->editor->remove(strlen($this->text));
}
}
// 利用例
$editor = new TextEditor();
$history = [];
$cmd1 = new TypeCommand($editor, "Hello ");
$cmd1->execute();
$history[] = $cmd1;
$cmd2 = new TypeCommand($editor, "World");
$cmd2->execute();
$history[] = $cmd2;
echo $editor->getContent() . "\n"; // Hello World
// Undo
$last = array_pop($history);
$last->undo();
echo $editor->getContent() . "\n"; // Hello
from abc import ABC, abstractmethod
class Command(ABC):
@abstractmethod
def execute(self): pass
@abstractmethod
def undo(self): pass
class TextEditor:
def __init__(self):
self.content = ""
def add(self, text: str):
self.content += text
def remove(self, length: int):
self.content = self.content[:-length]
def get_content(self) -> str:
return self.content
class TypeCommand(Command):
def __init__(self, editor: TextEditor, text: str):
self.editor = editor
self.text = text
def execute(self):
self.editor.add(self.text)
def undo(self):
self.editor.remove(len(self.text))
# 利用例
editor = TextEditor()
history: list[Command] = []
cmd1 = TypeCommand(editor, "Hello ")
cmd1.execute()
history.append(cmd1)
cmd2 = TypeCommand(editor, "World")
cmd2.execute()
history.append(cmd2)
print(editor.get_content()) # Hello World
# Undo
last = history.pop()
last.undo()
print(editor.get_content()) # Hello
✅ Explanation
This code uses the Command
pattern to encapsulate actions (like typing text) into command objects.
These command objects are stored in a history list and can be undone later using the undo()
method.
1. Overview of the Command Pattern
-
Command: Declares the interface for executing and undoing an operation
- Here:
Command
- Here:
-
ConcreteCommand: Implements the command interface and defines a binding between the action and the receiver
- Here:
TypeCommand
- Here:
-
Receiver: Knows how to perform the operations associated with a request
- Here:
TextEditor
- Here:
-
Invoker: Executes the command and stores it for potential undo
- Here: The
history
array serves this role
- Here: The
2. Key Classes and Their Roles
-
Command
- Defines
execute()
andundo()
methods
- Defines
-
TypeCommand
- A concrete implementation of
Command
- Adds text to the editor on
execute()
, and removes it onundo()
- A concrete implementation of
-
TextEditor
- The receiver of the command
- Manages the text buffer and provides the actual editing operations
-
Client Code
- Creates
TypeCommand
objects, executes them, and stores them in a history list - Can call
undo()
on the last command to reverse the operation
- Creates
3. UML Class Diagram
4. Benefits of the Command Pattern
- Encapsulation of Operations: Each action is self-contained and easy to store and execute later
- Undo/Redo Support: Commands can be stored and reversed using the
undo()
method - Flexible History Tracking: Enables logging, replaying, or testing actions independently
This pattern is especially useful when you need to track and manage user actions over time—providing a solid foundation for undo/redo systems and command histories.