definitionEncapsulate a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.“ The "command pattern" encapsulates "requests" into objects so that other objects can be parameterized using different requests, queues, or logs, while supporting undoable operations. The definition of "request" here is not the "Ajax request" that we often say on the front end, but an "action request", which means initiating an action. For example, when you turn off the TV using the remote control, "turn off" is a request. In the command pattern, we abstract the request into a command, which is reusable and only cares about its recipient (the TV). As for the initiator of the action (the remote control), it only cares about which commands it supports, but not what these commands do specifically. structureThe class diagram of the command pattern is as follows: In this class diagram, we see five roles:
Receiver and Invoker are not coupled. When the function needs to be expanded, a new Command is added. Therefore, the command mode complies with the open-closed principle. ExamplesCustom shortcut keysCustomizing shortcut keys is the most basic function of an editor. Through the command pattern, we can write a structure that decouples the key position from the key logic. interface Command { exec():void } type Keymap = { [key:string]: Command } class Hotkey { keymap: Keymap = {} constructor(keymap: Keymap) { this.keymap = keymap } call(e: KeyboardEvent) { const prefix = e.ctrlKey ? 'ctrl+' : '' const key = prefix + e.key this.dispatch(key) } dispatch(key: string) { this.keymap[key].exec() } } class CopyCommand implements Command { constructor(clipboard: any) {} exec() {} } class CutCommand implements Command { constructor(clipboard: any) {} exec() {} } class PasteCommand implements Command { constructor(clipboard: any) {} exec() {} } const clipboard = { data: '' } const keymap = { 'ctrl+x': new CutCommand(clipboard), 'ctrl+c': new CopyCommand(clipboard), 'ctrl+v': new PasteCommand(clipboard) } const hotkey = new Hotkey(keymap) document.onkeydown = (e) => { hotkey.call(e) } In this case, hotkey is the Invoker and clipboard is the Receiver. When we need to modify an existing keymap, we only need to add or replace the existing key or command. Do you think this writing style is familiar? Yes, Redux also applies the command mode. Store is equivalent to Receiver, Action is equivalent to Command, and Dispatch is equivalent to Invoker. Undo and RedoBased on the command pattern, we can easily extend it to support undo and redo. interface IPerson { moveTo(x: number, y: number): void } class Person implements Person { x = 0 y = 0 moveTo(x: number, y: number) { this.x = x this.y = y } } interface Command { exec(): void undo(): void } class MoveCommand implements Command { prevX = 0 prevY = 0 person: Person constructor(person: Person) { this.person = person } exec() { this.prevX = this.person.x this.prevY = this.person.y this.person.moveTo(this.prevX++, this.prevY++) } undo() { this.person.moveTo(this.prevX, this.prevY) } } const ezio = new Person() const moveCommand = new MoveCommand(ezio) moveCommand.exec() console.log(ezio.x, ezio.y) moveCommand.undo() console.log(ezio.x, ezio.y) Recording and playbackThink about the recording and playback function in the game. If each action of the character is regarded as a command, then a series of command queues can be obtained during recording. class Control { commands: Command[] = [] exec(command) { this.commands.push(command) command.exec(this.person) } } const ezio = new Person() const control = new Control() control.exec(new MoveCommand(ezio)) control.exec(new MoveCommand(ezio)) console.log(control.commands) When we have a command queue, we can easily perform multiple undo and redo operations and realize a command history. Just move the pointer of the current command queue. class CommandHistory { commands: Command[] = [] index = 0 get currentCommand() { return this.commands[index] } constructor(commands: Command[]) { this.commands = commands } redo() { this.index++ this.currentCommand.exec() } undo() { this.currentCommand.undo() this.index-- } } At the same time, if we serialize the command into an object, it can be used for storage and transmission. In this way, we can send it to the remote computer and realize the function of remotely controlling the movement of ezio. [{ type: 'move', x: 1, y: 1, }, { type: 'move', x: 2, y: 2, }] MacrosBy doing some simple processing on the Command, you can combine the existing commands and execute them, turning them into a macro command. class BatchedCommand implements Command { commands = [] constructor(commands) { this.commands = commands } exec() { this.commands.forEach(command => command.exec()) } } const batchedMoveCommand = new BatchedCommand([ new MoveCommand(ezio), new SitCommand(ezio), ]) batchedMoveCommand.exec() SummarizeThrough the above examples, we can see that the command mode has the following characteristics:
The above is a detailed explanation of the command mode in Javascript practice. For more information about the Javascript command mode, please pay attention to other related articles on 123WORDPRESS.COM! You may also be interested in:
|
<<: Introduction to common MySQL storage engines and parameter setting and tuning
>>: Implementation of Docker data volume operations
This time we set up an rtmp live broadcast server...
Table of contents Preface: Step 1: Find the free ...
Preface This article mainly introduces the releva...
BMP is an image file format that is independent o...
Table of contents Multi-table join query Inner Jo...
I recently read Yahoo's 34 Golden Rules and le...
Table of contents Preface What to use if not jQue...
This article records the installation tutorial of...
VMware Preparation CentOS preparation, here is Ce...
Table of contents 1. Introduction to Portainer 2....
1. Use the mysql/mysql-server:latest image to qui...
First check the kernel version you are using lin@...
1. Download the required packages wget -P /usr/lo...
01. Command Overview The gcc command uses the C/C...
Hexo binds a custom domain name to GitHub under W...