命令設計模式是一種廣為人知的設計模式,它屬于行為設計模式(“四人幫”的一部分)。 顧名思義,它與應用程序中的動作和事件有關。
問題陳述:
假設有一個網頁將在其中包含多個菜單的情況。 編寫此代碼的一種方法是使條件成立,并在每次單擊菜單時執行操作。
private void getAction(String action){if(action.equalsIgnoreCase('New')){//Create new file}else if(action.equalsIgnoreCase('Open')){//Open existing file}if(action.equalsIgnoreCase('Print')){//Print the file}if(action.equalsIgnoreCase('Exit')){//get out of the application}}
我們必須根據操作字符串執行操作。 但是,以上代碼如果條件太多,則無法擴展。
意圖:
- 動作的請求者需要與執行該動作的對象分離。
- 允許將請求封裝為對象。 注意這一行,因為這對于命令模式是非常重要的概念。
- 允許將請求存儲在隊列中,即允許您存儲稍后可以執行的操作列表。
解:
為了解決上述問題,這里可以使用命令模式。 如上所述,命令模式通過封裝將上述動作移至對象。 這些對象在執行時將執行命令。 在這里,每個命令都是一個對象。 因此,我們將必須為每個菜單操作(例如NewClass , OpenClass , PrintClass , ExitClass)創建單獨的類。 所有這些類都繼承自父接口(即Command接口)。 此接口(命令接口)抽象/包裝所有子動作類。
現在,我們介??紹一個Invoker類,其主要工作是將操作與具有該操作的類進行映射。 它基本上保留了該動作,并通過調用execute()方法獲得執行請求的命令。 糟糕! 我們在這里錯過了另一個利益相關者。 這是Receiver類。 接收器類具有執行操作的知識。 接收者具有執行動作時該做什么的知識。
結構體:
以下是“命令設計”模式的參與者:
- 命令–這是用于執行操作的界面。
- ConcreteCommand –此類擴展了Command接口并實現了execute方法。 此類在操作和接收者之間創建綁定。
- 客戶端–此類創建ConcreteCommand類并將其與接收者相關聯。
- 調用程序–此類要求命令執行請求。
- 接收器–此類知道要執行的操作。
范例 :
腳步:
- 使用諸如execute()之類的方法簽名定義Command接口。 在上面的示例中, ActionListenerCommand是具有單個execute()方法的命令界面。
- 創建一個或多個派生類,這些派生類封裝以下內容的一些子集:“接收者”對象,要調用的方法,要傳遞的參數。 在上面的示例中, ActionOpen和ActionSave是Concrete命令類,它們在接收者和操作之間創建綁定。 ActionOpen類在execute()內調用接收方(在本例中為Document類)類的action方法。 因此,命令接收器類需要做什么。
- 為每個延遲的執行請求實例化Command對象。
- 將Command對象從創建者傳遞到調用者。
- 調用者決定何時執行()。
- 客戶端實例化Receiver對象(Document)和Command對象,并允許調用者調用命令。
代碼示例:
命令界面:
public interface ActionListenerCommand {public void execute();
}
接收器類別:
public class Document {public void Open(){System.out.println('Document Opened');}public void Save(){System.out.println('Document Saved');}
}
具體命令:
public class ActionOpen implements ActionListenerCommand {private Document adoc;public ActionOpen(Document doc) {this.adoc = doc;}@Overridepublic void execute() {adoc.Open();}
}
祈求者等級:
public class MenuOptions {private ActionListenerCommand openCommand;private ActionListenerCommand saveCommand;public MenuOptions(ActionListenerCommand open, ActionListenerCommand save) {this.openCommand = open;this.saveCommand = save;}
public void clickOpen(){openCommand.execute();
}
public void clickSave(){saveCommand.execute();
}
}
客戶類別 :
public class Client {public static void main(String[] args) {Document doc = new Document();ActionListenerCommand clickOpen = new ActionOpen(doc);ActionListenerCommand clickSave = new ActionSave(doc);MenuOptions menu = new MenuOptions(clickOpen, clickSave);menu.clickOpen();menu.clickSave();}}
優點:
命令模式有助于解耦調用方和接收方。 接收者是知道如何執行動作的人。
命令應能夠執行撤消和重做操作。
這種模式在可擴展性方面有所幫助,因為我們可以在不更改現有代碼的情況下添加新命令。
退稅:
命令模式的主要缺點是每個單獨命令的類數增加。 這些項目也可以通過方法實現來完成。 但是,命令模式類比使用if else條件創建多個方法更具可讀性。
有趣的一點:
- java.lang.Runnable和javax.swing.Action的實現遵循命令設計模式。
- 命令可以使用Memento來維護撤消操作所需的狀態。
下載示例代碼:
參考:來自您的JCG合作伙伴 Mainak Goswami的命令 ,位于Idiotechie博客上。
翻譯自: https://www.javacodegeeks.com/2012/11/by-your-command-command-design-pattern.html