小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

命令模式.

 新進小設(shè)計 2020-07-19

一、概念

  • 命令模式:將“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數(shù)化其他對象。命令模式也支持可撤銷的操作。
  • 角色:
    ?1、命令(Command):為所有命令聲明了一個接口。調(diào)用命令對象的 execute()方法,就可以讓接收者進行相關(guān)的操作。這個接口也具備一個 undo() 方法。
    ?2、具體命令(ConcreteCommand):實現(xiàn)命令接口,定義了動作和接收者之間的綁定關(guān)系。調(diào)用者只要調(diào)用 execute() 就可以發(fā)出請求,然后由 ConcreteCommand 調(diào)用接收者的一個或多個動作。
    ?3、請求者(Invoker):持有一個命令對象,有一個行動方法,在某個時間點調(diào)用命令對象的 execute() 方法,將請求付諸實行。
    ?4、接收者(Receiver):接收者知道如何進行必要的動作,實現(xiàn)這個請求。任何類都可以當接收者。
    ?5、客戶端(Client):創(chuàng)建一個具體命令(ConcreteCommand)對象并確定其接收者,包括把其他角色串連在一起。

avatar

二、Demo 實現(xiàn)

Topic:我們要制作一個簡易的遙控器,有兩個控制燈開關(guān)的按鈕,并有一個操作回退按鈕。

1、接收者

?首先,我們先來定義一個接收者的角色,也就是最后執(zhí)行動作的那個對象 —— Light.java,控制著燈的開啟和關(guān)閉。

public class Light {

    public void on() {
        System.out.println("燈亮了...");
    }

    public void off() {
        System.out.println("燈暗了...");
    }
}

2、命令

?現(xiàn)在,我們要定義一個命令角色。一般是一個接口,為所有的命令對象聲明一個接口,規(guī)范將要進行的命令操作。

public interface Command {
    /**
     * 執(zhí)行命令
     */
    void execute();

    /**
     * 撤銷命令
     */
    void undo();
}

3、具體命令

?有了命名角色后,我們要構(gòu)建具體命令角色。具體命令實現(xiàn)了命令接口,定義了動作和接收者之間的綁定關(guān)系。這里,我們有兩個具體命令對象—— LightOnCommand.java(開燈命令)、LightOffCommand.java(關(guān)燈命令)

public class LightOnCommand implements Command {

    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }
}
public class LightOffCommand implements Command {

    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.off();
    }

    @Override
    public void undo() {
        light.on();
    }
}

4、請求者

?前面,我們定義了動作的接收方和聯(lián)系中介 —— 命名對象?,F(xiàn)在,我們要著手構(gòu)建請求者角色了。請求者持有一個命令對象,有一個行動方法。它會在某個時間點執(zhí)行行動方法,但不關(guān)心是誰具體執(zhí)行了這個動作。

public class RemoteInvoker {

    /**
     * 開關(guān)命令數(shù)組,模擬有很多對開關(guān)數(shù)組
     */
    private Command[] onCommands;
    private Command[] offCommands;
    /**
     * 撤銷(回退)命令
     */
    private Command undoCommand;

    public RemoteInvoker(int length) {
        // 有幾組開關(guān),就設(shè)置多少數(shù)組
        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;
        }
    }

    /**
     * @Description 設(shè)置命令對象
     * @date 2018/11/29 09:15
     * @param slot 遙控器的位置
     * @param onCommand 開的命令
     * @param offCommand 關(guān)的命令
     * @return void
     */
    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();
    }
}

5、客戶端

?前面,我們定義好了請求者、接收者已經(jīng)兩者之間的聯(lián)系中介 —— 命令對象。但是這幾個角色對象之間都是松耦合的,還沒有一個具體動作的流程,現(xiàn)在我們利用客戶端角色把整個動作流程串聯(lián)在一起。

public class RemoteClient {

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

avatar

三、總結(jié)

  • 命令模式將發(fā)出請求的對象和執(zhí)行請求的對象解耦,在被解耦的兩者之間是通過命令對象進行溝通的。
  • 一個命令對象通過在特定接收者上綁定一組動作來封裝一個請求。要達到這一點,命令對象將接收者和動作封裝進對象中,這個對象只暴露出一個 execute() 方法,當此方法被調(diào)用時,接收者就會進行這些動作。從外面來看,其他對象不知道究竟哪個接收者進行了哪些操作,只知道如果調(diào)用 execute() 方法,請求的目的就可以達到。
  • 當你不想返回一個有意義的對象時,空對象就很有用。這樣,我們就可以把處理 null 的責任轉(zhuǎn)移給空對象,甚至有些時候,空對象本身也被視為一種設(shè)計模式。
  • 我們還可以把一堆命令組裝起來拼成一個命令,稱為宏命令。宏命令是命令的一種延伸,允許調(diào)用一系列的命令。包括一系列的執(zhí)行和撤銷動作。
  • 適用場景:
    ?1、命令的發(fā)送者和命令執(zhí)行者有不同的生命周期,命令發(fā)送了并不是立即執(zhí)行。換言之,原先的請求發(fā)出者可能已經(jīng)不在了,而命令對象本身仍然是活動的。這時命令的接收者可以是在本地,也可以在網(wǎng)絡(luò)的另外一個地址。命令對象可以在序列化之后傳送到另外一臺機器上去。 ?2、命令需要進行各種管理邏輯,比如:對多個命令的統(tǒng)一控制。
    ?3、需要支持撤消/重試操作。命令對象可以把狀態(tài)存儲起來,等到客戶端需要撤銷命令所產(chǎn)生的效果時,可以調(diào)用 undo()方法,把命令所產(chǎn)生的效果撤銷掉。命令對象還可以提供 redo()方法, 以供客戶端在需要時再重新實施命令效果。 ?4、使用命令模式作為 "回調(diào)(callBack)" 在面向?qū)ο笙到y(tǒng)中的替代。"callBack" 講的便是先將一個函數(shù)登記上,然后在以后調(diào)用此函數(shù)。 ?5、如果要將系統(tǒng)中所有的數(shù)據(jù)更新到日志里,以便在系統(tǒng)崩潰時,可以根據(jù)日志讀回所有的數(shù)據(jù)更新命令,重新調(diào)用 execute() 方法一條一條執(zhí)行這些命令,從而恢復系統(tǒng)在崩潰前所做的數(shù)據(jù)更新。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多