发布于 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)