一、命令模式定义与核心思想
命令模式(Command Pattern) 是一种行为型设计模式,其核心是将请求 或操作封装为独立对象,实现调用者(发送请求)与接收者(执行操作)的解耦。通过这种方式,可以灵活管理请求的队列化、撤销、重做等复杂逻辑。
- 核心思想:将"动作"抽象为可传递、存储的对象,使得操作本身具备独立性和可扩展性。
二、命令模式的结构组成
角色 | 作用 |
---|---|
Command | 抽象命令接口,声明执行方法(如 execute() )。 |
ConcreteCommand | 具体命令类,绑定接收者并实现操作细节(如复制、粘贴命令)。 |
Receiver | 实际操作执行者(如编辑器、DOM元素)。 |
Invoker | 调用者,触发命令执行(如按钮、任务调度器)。 |
三、应用场景与意义
1. 典型应用场景
- 需要支持撤销/重做:例如文本编辑器的操作历史记录47。
- 多步骤任务管理:如批量表单提交、动画序列执行46。
- 复杂交互解耦:按钮点击触发不同业务逻辑,避免代码冗余57。
2. 核心意义
- 解耦调用与执行:发送者无需关注接收者的具体实现。
- 灵活扩展性:新增命令无需修改现有代码(符合开闭原则)。
- 操作管理能力:支持队列化、日志记录、事务处理等高级功能。
四、由浅入深的三层案例
1. 基础示例:按钮触发命令
javascript
// 命令接口
class Command {
execute() {}
}
// 具体命令:切换主题
class ToggleThemeCommand extends Command {
constructor(receiver) {
super();
this.receiver = receiver; // Receiver为DOM元素
}
execute() {
this.receiver.classList.toggle('dark-mode');
}
}
// 调用者:按钮绑定命令
const button = document.getElementById('theme-btn');
button.onclick = new ToggleThemeCommand(document.body).execute;
关键点:按钮(Invoker)与DOM操作(Receiver)解耦,支持动态替换命令。
2. 进阶示例:支持撤销的操作历史
kotlin
class HistoryManager {
constructor() {
this.stack = [];
}
push(command) {
this.stack.push(command);
}
undo() {
const command = this.stack.pop();
command?.undo(); // 命令需实现undo方法
}
}
// 具体命令:文本输入(支持撤销)
class TextInputCommand {
constructor(editor, newText) {
this.editor = editor;
this.prevText = editor.textContent;
this.newText = newText;
}
execute() {
this.editor.textContent = this.newText;
}
undo() {
this.editor.textContent = this.prevText;
}
}
// 使用示例
const editor = document.getElementById('editor');
const history = new HistoryManager();
history.push(new TextInputCommand(editor, 'Hello World'));
history.undo(); // 恢复为原始文本
关键点:通过命令对象记录操作状态,实现撤销功能。
3. 高阶示例:动画队列调度
javascript
class AnimationQueue {
constructor() {
this.queue = [];
}
addCommand(command) {
this.queue.push(command);
}
run() {
this.queue.reduce((prev, cmd) =>
prev.then(() => cmd.execute()), Promise.resolve()
);
}
}
// 具体命令:DOM元素动画
class MoveCommand {
constructor(element, x, y) {
this.element = element;
this.x = x;
this.y = y;
}
execute() {
return new Promise(resolve => {
this.element.style.transform = `translate(${this.x}px, ${this.y}px)`;
this.element.addEventListener('transitionend', resolve);
});
}
}
// 使用示例
const box = document.getElementById('box');
const queue = new AnimationQueue();
queue.addCommand(new MoveCommand(box, 100, 0));
queue.addCommand(new MoveCommand(box, 100, 100));
queue.run(); // 顺序执行动画
关键点:通过命令队列管理异步操作,实现复杂动画序列。
命令模式通过将操作对象化,解决了前端开发中调用与执行的强耦合问题,适用于需要动态管理、扩展或记录用户交互的场景。从简单的按钮绑定到复杂的任务队列,其分层设计思想能够显著提升代码的可维护性和灵活性。