設計模式筆記15——命令模式(command)

智能生活項目需求
1) 我們買了一套智能家電,有照明燈、風扇、冰箱、洗衣機,我們只要在手機上安裝app就可以控制對這些家電工作。
2) 這些智能家電來自不同的廠家,我們不想針對每一種家電都安裝一個App,分別控制,我們希望只要一個app就可以控制全部智能家電。
3) 要實現一個app控制所有智能家電的需要,則每個智能家電廠家都要提供一個統一的接口給app調用,這時 就可以考慮使用命令模式。
4) 命令模式可將“動作的請求者”從“動作的執行者”對象中解耦出來.
5) 在我們的例子中,動作的請求者是手機app,動作的執行者是每個廠商的一個家電產品

 

命令模式基本介紹
1) 命令模式(Command Pattern):在軟件設計中,我們經常需要向某些對象發送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需在程序運行時指定具體的請求接收者即可,此時,可以使用命令模式來進行設計
2) 命名模式使得請求發送者與請求接收者消除彼此之間的耦合,讓對象之間的調用關係更加靈活,實現解耦。
3) 在命名模式中,會將一個請求封裝爲一個對象,以便使用不同參數來表示不同的請求(即命名),同時命令模式也支持可撤銷的操作。
4) 通俗易懂的理解:將軍發佈命令,士兵去執行。其中有幾個角色:將軍(命令發佈者)、士兵(命令的具體執行者)、命令(連接將軍和士兵)。

Invoker是調用者(將軍),Receiver是被調用者(士兵),
MyCommand是命令,實現了Command接口,持有接收對象

命令模式的原理類圖

對原理類圖的說明-即(命名模式的角色及職責)

1) Invoker 是調用者角色

2) Command: 是命令角色,需要執行的所有命令都在這裏,可以是接口或抽象類

3) Receiver: 接受者角色,知道如何實施和執行一個請求相關的操作

4) ConcreteCommand: 將一個接受者對象與一個動作綁定,調用接受者相應的操作,實現execute

 

核心代碼:

調用部分:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        //使用命令設計模式,完成通過遙控器,對電燈的操作
        
        //創建電燈的對象(接受者)
        LightReceiver lightReceiver = new LightReceiver();
        
        //創建電燈相關的開關命令
        LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
        LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
        
        //需要一個遙控器
        RemoteController remoteController = new RemoteController();
        
        //給我們的遙控器設置命令, 比如 no = 0 是電燈的開和關的操作
        remoteController.setCommand(0, lightOnCommand, lightOffCommand);
        
        System.out.println("--------按下燈的開按鈕-----------");
        remoteController.onButtonWasPushed(0);
}


    // 按下開按鈕
    public void onButtonWasPushed(int no) { // no 0
        // 找到你按下的開的按鈕, 並調用對應方法
        onCommands[no].execute();
        // 記錄這次的操作,用於撤銷
        undoCommand = onCommands[no];
    }
//也就是每一個命令有記錄,方便後續的取消
而 execute()實際上調用的是接收者來處理命令:
    public void execute() {
        // TODO Auto-generated method stub
        //調用接收者的方法
        light.on();
    }
 

這裏原理的核心代碼已經實現,但是如何保存命令的,我覺得可以採用隊列,先進先出,而且只保留最近的幾個命令。

 

 

命令模式的注意事項和細節

1) 將發起請求的對象與執行請求的對象解耦。發起請求的對象是調用者,調用者只要調用命令對象的execute()方法就可以讓接收者工作,而不必知道具體的接收者對象是誰、是如何實現的,命令對象會負責讓接收者執行請求的動作,也就是說:”請求發起者”和“請求執行者”之間的解耦是通過命令對象實現的,命令對象起到了紐帶橋樑的作用。

2) 容易設計一個命令隊列。只要把命令對象放到列隊,就可以多線程的執行命令

3) 容易實現對請求的撤銷和重做

4) 命令模式不足:可能導致某些系統有過多的具體命令類,增加了系統的複雜度,這點在在使用的時候要注意

5) 空命令也是一種設計模式,它爲我們省去了判空的操作。在上面的實例中,如果沒有用空命令,我們每按下一個按鍵都要判空,這給我們編碼帶來一定的麻煩。

6) 命令模式經典的應用場景:界面的一個按鈕都是一條命令、模擬CMD(DOS命令)訂單的撤銷/恢復、觸發-反饋機制

 

 

 

 

 

 

 

 

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