智能生活項目需求
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命令)訂單的撤銷/恢復、觸發-反饋機制