发布于 2024 年 2 月 26 日,星期一
“全能指挥官:玩转JavaScript命令模式,让代码听你的话!”揭示了命令模式在JavaScript中的核心作用。命令模式通过将请求封装为对象,使代码更具灵活性和可扩展性,开发者可以像指挥官一样精确控制代码行为。它将操作和执行分离,使得代码更易于维护和测试,同时支持撤销、重做等复杂操作。通过命令模式,开发者能够更高效地管理代码逻辑,提升代码的可读性和可维护性,实现对代码行为的全面掌控。
系列首发于公众号『非同质前端札记』https://mp.weixin.qq.com/s?__biz=MzkyOTI2MzE0MQ==&mid=2247485576&idx=1&sn=5ddfe93f427f05f5d126dead859d0dc8&chksm=c20d73c2f57afad4bbea380dfa1bcc15367a4cc06bf5dd0603100e8bd7bb317009fa65442cdb&token=1071012447&lang=zh_CN#rd ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。
// 命令接口
class Command {
execute() {}
}
// 具体命令:打开文档
class OpenDocumentCommand extends Command {
constructor(document) {
super();
this.document = document;
}
// 执行打开文档命令
execute() {
this.document.open();
}
}
// 具体命令:保存文档
class SaveDocumentCommand extends Command {
constructor(document) {
super();
this.document = document;
}
// 执行保存文档命令
execute() {
this.document.save();
}
}
// 接收者:文档
class Document {
open() {
console.log("打开文档");
}
save() {
console.log("保存文档");
}
}
// 调用者:按钮
class Button {
constructor(command) {
this.command = command;
}
// 点击按钮执行命令
click() {
this.command.execute();
}
}
// 使用示例
const document = new Document();
// 创建打开文档命令并关联文档对象
const openCommand = new OpenDocumentCommand(document);
// 创建保存文档命令并关联文档对象
const saveCommand = new SaveDocumentCommand(document);
// 创建按钮并关联打开文档命令
const openButton = new Button(openCommand);
// 创建按钮并关联保存文档命令
const saveButton = new Button(saveCommand);
// 点击按钮执行命令
openButton.click(); // 打开文档
saveButton.click(); // 保存文档
// 命令接口
class Command {
execute() {}
undo() {}
redo() {}
}
// 具体命令:打开文档
class OpenDocumentCommand extends Command {
constructor(document) {
super();
this.document = document;
}
execute() {
this.document.open();
}
undo() {
this.document.close();
}
redo() {
this.execute();
}
}
// 具体命令:保存文档
class SaveDocumentCommand extends Command {
constructor(document) {
super();
this.document = document;
}
execute() {
this.document.save();
}
undo() {
// 撤销保存操作,恢复文档到上一个保存点或初始状态
this.document.restore();
}
redo() {
this.execute();
}
}
// 接收者:文档
class Document {
constructor(name) {
this.name = name;
this.content = "";
this.savedContent = "";
}
open() {
console.log(`打开文档:${this.name}`);
}
close() {
console.log(`关闭文档:${this.name}`);
}
save() {
this.savedContent = this.content;
console.log(`保存文档:${this.name}`);
}
restore() {
this.content = this.savedContent;
console.log(`恢复文档:${this.name}`);
}
setContent(content) {
this.content = content;
console.log(`设置文档内容:${this.name}`);
}
getContent() {
return this.content;
}
}
// 调用者:按钮
class Button {
constructor() {
this.commandQueue = [];
this.undoStack = [];
this.redoStack = [];
}
// 将命令加入队列
addToQueue(command) {
this.commandQueue.push(command);
}
// 执行队列中的命令
executeQueue() {
console.log("执行命令队列:");
while (this.commandQueue.length > 0) {
const command = this.commandQueue.shift();
command.execute();
this.undoStack.push(command);
}
}
// 撤销上一次执行的命令
undo() {
if (this.undoStack.length === 0) {
console.log("没有可撤销的命令");
return;
}
const command = this.undoStack.pop();
command.undo();
this.redoStack.push(command);
console.log("撤销上一次命令");
}
// 重做上一次撤销的命令
redo() {
if (this.redoStack.length === 0) {
console.log("没有可重做的命令");
return;
}
const command = this.redoStack.pop();
command.redo();
this.undoStack.push(command);
console.log("重做上一次撤销的命令");
}
}
// 使用示例
const document = new Document("example.txt");
// 创建按钮
const button = new Button();
// 创建打开文档命令并关联文档对象
const openCommand = new OpenDocumentCommand(document);
// 创建保存文档命令并关联文档对象
const saveCommand = new SaveDocumentCommand(document);
// 将命令加入队列
button.addToQueue(openCommand);
button.addToQueue(saveCommand);
// 执行命令队列
button.executeQueue();
// 撤销命令
button.undo();
// 重做命令
button.redo();
Q:(question)
R:(result)
A:(attention matters)
D:(detail info)
S:(summary)
Ana:(analysis)
T:(tips)