亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

詳解Javascript實(shí)踐中的命令模式

瀏覽:20日期:2023-06-04 17:34:05
定義

Encapsulate a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests,and support undoable operations.“

「命令模式」將「請(qǐng)求」封裝成對(duì)象,以便使用不同的請(qǐng)求、隊(duì)列或者日志來參數(shù)化其他對(duì)象,同時(shí)支持可撤消的操作。

這里的「請(qǐng)求」的定義,并不是我們前端常說的「Ajax 請(qǐng)求」,而是一個(gè)「動(dòng)作請(qǐng)求」,也就是發(fā)起一個(gè)行為。例如,通過遙控器關(guān)閉電視,這里的「關(guān)閉」就是一個(gè)請(qǐng)求。在命令模式中,我們將請(qǐng)求抽象成一個(gè)命令,這個(gè)命令是可復(fù)用的,它只關(guān)心它的接受者(電視);而對(duì)于動(dòng)作的發(fā)起者(遙控器)來說,它只關(guān)心它所支持的命令有哪些,而不關(guān)心這些命令具體是做什么的。

結(jié)構(gòu)

命令模式的類圖如下:

詳解Javascript實(shí)踐中的命令模式

在該類圖中,我們看到五個(gè)角色:

Client - 創(chuàng)建 Concrete Command 與 Receiver(應(yīng)用層)。 Invoker - 命令的發(fā)出者,通常會(huì)持有命令對(duì)象,可以持有很多的命令對(duì)象。 Receiver - 命令接收者,真正執(zhí)行命令的對(duì)象。任何類都可能成為一個(gè)接收者,只要它能夠?qū)崿F(xiàn)命令要求實(shí)現(xiàn)的相應(yīng)功能。 Command - 命令接口。 ConcreteCommand - 命令接口的實(shí)現(xiàn)。

Reciver 與 Invoker 沒有耦合,當(dāng)需要拓展功能時(shí),通過新增 Command,因此命令模式符合開閉原則。

實(shí)例自定義快捷鍵

自定義快捷鍵是一個(gè)編輯器的最基本功能。通過命令模式,我們可以寫出一個(gè)將鍵位與鍵位邏輯解耦的結(jié)構(gòu)。

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.keythis.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)}

在本例中,hotkey是 Invoker,clipboard是 Receiver。當(dāng)我們需要修改已有的 keymap 時(shí),只需要新增或替換已有的key或Command即可。

是不是覺得這個(gè)寫法似曾相識(shí)?沒錯(cuò)Redux 也是應(yīng)用了命令模式,Store 相當(dāng)于 Receiver,Action 相當(dāng)于 Command,Dispatch 相當(dāng)于 Invoker。

撤銷與重做

基于命令模式,我們可以很容易拓展,使它支持撤銷與重做。

interface IPerson { moveTo(x: number, y: number): void}class Person implements Person { x = 0 y = 0 moveTo(x: number, y: number) {this.x = xthis.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.xthis.prevY = this.person.ythis.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)錄制與回放

想想我們?cè)谟螒蛑械匿浿婆c回放功能,如果將角色的每個(gè)動(dòng)作都作為一個(gè)命令的話,那么在錄制時(shí)就能夠得到一連串的命令隊(duì)列。

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)

當(dāng)我們有了命令隊(duì)列,我們又能夠很容易得進(jìn)行多次的撤銷和重做,實(shí)現(xiàn)一個(gè)命令的歷史記錄。只需要移動(dòng)當(dāng)前命令隊(duì)列的指針即可。

class CommandHistory { commands: Command[] = []index = 0get currentCommand() {return this.commands[index] }constructor(commands: Command[]) {this.commands = commands }redo() {this.index++this.currentCommand.exec() }undo() {this.currentCommand.undo()this.index-- }}

同時(shí),如果我們將命令序列化成一個(gè)對(duì)象,它便可以用于保存與傳遞。這樣我們將它發(fā)送到遠(yuǎn)程計(jì)算機(jī),就能實(shí)現(xiàn)遠(yuǎn)程控制ezio移動(dòng)的功能。

[{ type: ’move’, x: 1, y: 1,}, { type: ’move’, x: 2, y: 2,}]宏命令

對(duì)Command進(jìn)行一些簡(jiǎn)單的處理就能夠?qū)⒁延械拿罱M合起來執(zhí)行,將其變成一個(gè)宏命令。

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()總結(jié)

通過以上幾個(gè)例子,我們可以看出命令模式有一下幾個(gè)特點(diǎn):

低耦合,徹底消除了接受者與調(diào)用者之間的耦合。 易拓展,只需要增加新的命令便可拓展出新功能。 支持序列化,易于實(shí)現(xiàn)保存與傳遞。 容易導(dǎo)致 Command 類龐大。

以上就是詳解Javascript實(shí)踐中的命令模式的詳細(xì)內(nèi)容,更多關(guān)于Javascript命令模式的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 在线观看爱爱视频 | 国产尻逼 | 免费人成视网站在线不卡 | 特级理论片 | 天天射色综合 | 黄色网久久 | 可以在线看黄的网站 | 一区欧美 | 护士和黑人做爰 | 欧美亚洲国产一区 | 华人欧美国产在线精品 | 伊人精品| 97超级碰碰碰久久久观看 | 黄色一区二区三区 | 欧美午夜免费毛片a级 | 国产在线综合视频 | 黄片毛片免费在线观看 | 男人午夜免费视频 | 免费在线观看黄色的网站 | 河南毛片 | 国产免费亚洲 | 欧美做a一级视频免费观看 欧美做a欧美 | 成人日b视频 | 一区二区三区视频在线观看 | 欧美一级免费观看 | 亚洲人成网站在线在线 | 成人午夜做爰视频免费看 | 国产一级理论免费版 | 久久久久久久国产精品 | 亚洲第一视频在线观看 | 精品国产成人在线 | 狠狠色丁香九九婷婷综合五月 | 中日毛片| 国产性高清在线观看 | 亚洲第一视频在线 | 一区二区三区四区在线观看视频 | 国产免费福利网站 | 亚欧黄色| 国产精品一区在线播放 | 国产亚洲精品第一区在线观看 | 久青草免费视频手机在线观看 |