命令模式 :封裝調用

定義

命令模式將"請求"封裝成對象,以便使用不同的請求、隊列或者日誌來參數化其它對象。命令模式也支持可撤銷的操作。

命令模式設計圖
在這裏插入圖片描述

模式的意義

命令模式,主要的是將請求對象和執行對象進行解耦,也就是類圖裏面的Invoker和Receiver,這個模式主切入的點很小,但是應用很廣,也是解耦思想一個比較重要的模式。

// 命令接口
public interface Command {  
    void execute(); 
    void undo();
}
// 開燈功能
public class LightOnCommand implements Command {

    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
    public void undo() {
        light.off();
    }
// 關燈命令   
public class LightOffCommand implements Command {

    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.off();
    }
    public void undo() {
        light.on();
    }
}

public class RemoteInvoker {

    /**
     * 開關命令數組,模擬有很多對開關數組
     */
    private Command[] onCommands;
    private Command[] offCommands;
  
    private Command undoCommand;

    public RemoteInvoker(int length) {
        // 有幾組開關,就設置多少數組
        onCommands = new Command[length];
        offCommands = new Command[length];
        // 把每個命令初始化成空命令,避免空指針異常
        Command noCommand = new NoCommand();
        undoCommand = noCommand;
        for (int i = 0; i < length; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
    }

    public void setCommond(int slot, Command onCommand, Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }


    public void onButton(int slot) {
        onCommands[slot].execute();   
        undoCommand = onCommands[slot];
    }

    public void offButton(int slot) {
        offCommands[slot].execute();      
        undoCommand = offCommands[slot];
    }

    public void undoButton() {
        undoCommand.undo();
    }
}

客戶端

public class RemoteClient {

    public static void main(String[] args) {
        // 1、創建接收者
        Light light = new Light();
        // 2、創建命令對象
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        LightOffCommand lightOffCommand = new LightOffCommand(light);
        // 3、創建一組開關並用命令對象裝載它
        RemoteInvoker invoker = new RemoteInvoker(1);
        invoker.setCommond(0, lightOnCommand, lightOffCommand);
        // 4、測試
        invoker.onButton(0);
        invoker.offButton(0);
        invoker.undoButton();
    }
}

隊列

命令可以將運算打包,放入一個我們設置的工作隊列裏面,一端負責添加命令,然後另一端則是線程,線程從隊列中取出一個命令,調用他的execute()方法,等待這個調用完成,然後將此命令對象丟棄,再取出下一個命令。我們之前用Redis設計搶紅包的時候,就是將用戶搶到的紅包對象放到隊列裏面,然後由線程循環的將這個對象消耗掉,雖然沒有利用命令繼承,但也是這種概念的簡化版。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章