Command Objects

A command object packages an operation with its arguments. Because the operation becomes data, an invoker can schedule it, keep a history for undo, cancel or batch it, or serialize it for another machine. Editor undo stacks and collaborative editing (operational transformation) build on this pattern.

Commands with undo and serializationJavaScriptLive
const feed = new Set();                                  // the receiver
class Post {                                             // a command: action + arguments
  constructor(text) { this.text = text; }
  execute() { feed.add(this.text); }  undo() { feed.delete(this.text); }
  toJSON() { return { type: 'post', text: this.text }; }  // serializable for the network
}
class Invoker {
  #history = [];
  run(cmd) { cmd.execute(); this.#history.push(cmd); }
  undo() { this.#history.pop()?.undo(); }
}
const inv = new Invoker();
['Hi!', 'Typo!'].forEach((text) => inv.run(new Post(text))); inv.undo();
console.log([...feed], JSON.stringify(new Post('Later')));