1. 程式人生 > 實用技巧 >Golang Gin(下)

Golang Gin(下)

命令模式

命令模式Command Pattern是一種資料驅動的設計模式,其屬於行為型模式,別名為動作Action模式或事務Transaction模式,命令模式將請求以命令的形式包裹在物件中,並傳給呼叫物件,呼叫物件尋找可以處理該命令的合適的物件,並把該命令傳給相應的物件,該物件對請求排隊或者記錄請求日誌,以及支援可撤銷的操作。

描述

在軟體設計中,我們經常需要向某些物件傳送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需在程式執行時指定具體的請求接收者即可,此時,可以使用命令模式來進行設計,使得請求傳送者與請求接收者消除彼此之間的耦合,讓物件之間的呼叫關係更加靈活。命令模式可以對傳送者和接收者完全解耦,傳送者與接收者之間沒有直接引用關係,傳送請求的物件只需要知道如何傳送請求,而不必知道如何完成請求。命令模式也可以用於實現基於事務的系統,一旦執行命令,便會繼續保留命令的歷史記錄,如果最終命令成功執行,那麼一切都很好,否則只需遍歷歷史記錄並繼續對所有已執行的命令執行撤消即可。

優點

  • 降低系統的耦合度。
  • 新的命令可以很容易地加入到系統中。
  • 可以比較容易地設計一個命令佇列和巨集命令(組合命令)。
  • 可以方便地實現對請求的Undo和Redo。

缺點

  • 使用命令模式可能會導致某些系統有過多的具體命令類。因為針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用。

適用環境

  • 系統需要將請求呼叫者和請求接收者解耦,使得呼叫者和接收者不直接互動。
  • 系統需要在不同的時間指定請求、將請求排隊和執行請求。
  • 系統需要支援命令的撤銷Undo操作和恢復Redo操作。
  • 系統需要將一組操作組合在一起,即支援巨集命令

實現

// 假設我們有一個電燈,我們使用遙控器對其進行控制

class Bulb {
    turnOn() {
        console.log("Bulb has been lit!");
    }
    
    turnOff() {
        console.log("Darkness!");
    }
}

class Command {
    execute(){
        throw new Error("Abstract method cannot be called");
    }

    redo(){
        throw new Error("Abstract method cannot be called");
    }

    undo(){
        throw new Error("Abstract method cannot be called");
    }
}

class TurnOnCommand extends Command{
    constructor(bulb) {
        super();
        this.bulb = bulb;
    }
    
    execute() {
        this.bulb.turnOn();
    }
    
    undo() {
        this.bulb.turnOff();
    }
    
    redo() {
        this.execute();
    }
}

class TurnOffCommand extends Command {
    constructor(bulb) {
        super();
        this.bulb = bulb;
    }
    
    execute() {
        this.bulb.turnOff();
    }
    
    undo() {
        this.bulb.turnOn();
    }
    
    redo() {
        this.execute();
    }
}

class RemoteControl {
    submit(command) {
        command.execute();
    }
}

(function(){
    var bulb = new Bulb();

    var turnOn = new TurnOnCommand(bulb);
    var turnOff = new TurnOffCommand(bulb);

    var remote = new RemoteControl();
    remote.submit(turnOn); // Bulb has been lit!
    remote.submit(turnOff); // Darkness!
})();

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

https://www.runoob.com/design-pattern/command-pattern.html
https://github.com/sohamkamani/javascript-design-patterns-for-humans#-command
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/command.html