摘要:命令模式屬于行為型模式的一種,又稱為行動模式或交易模式。結構圖模式結構抽象命令類聲明了用于執行請求的的等方法具體命令類抽象命令類的子類,對應具體的接收者對象,將接收者對象的動作綁定其中。
概述命令模式(Command Pattern)屬于行為型模式的一種,又稱為行動(Action)模式或交易(Transaction)模式。將一個請求封裝為一個對象,從而達到用不同的請求對客戶進行參數化,對于排隊請求或請求日志記錄,可以提供命令的撤銷和恢復功能。
命令模式:對命令的封裝,把發送命令和執行命令的責任分割開,分別委派給不同的對象,每一個命令都是一個操作,允許請求方與接收方獨立開來,使之請求方不必清楚接收方的接口,更不必知道請求是怎么被接收,以及操作是否被執行、何時被執行,以及是怎么被執行的。
UML結構圖
模式結構
Command(抽象命令類): 聲明了用于執行請求的的exceute()等方法
ConcreteCommand(具體命令類): 抽象命令類的子類,對應具體的接收者對象,將接收者對象的動作綁定其中。在實現execute()方
法時,將調用接收者對象的相關操作(Action)。
Invoker(調用者): 調用命令對象執行請求,相關的方法叫做行動方法。
Receiver(接收者): 負責具體實施和執行一個請求。任何一個類都可以成為接收者,實施和執行請求的方法叫做行動方法。
案例博主比較喜歡聽歌,這里就以MusicPlayer(音樂播放器)為案例,一般播放器中都有播放(play),跳過(skip),停止(stop)等功能,是一種比較典型的命令模式
UML圖如下:
1.定義Command(抽象命令類),只有一個execute()用來執行命令
interface Command { void execute(); }
2.創建不同指令的ConcreteCommand(具體命令類)
class PlayCommand implements Command { private MusicPlayer musicPlayer; public PlayCommand(MusicPlayer musicPlayer) { this.musicPlayer = musicPlayer; } @Override public void execute() { musicPlayer.play(); } } class SkipCommand implements Command { private MusicPlayer musicPlayer; public SkipCommand(MusicPlayer musicPlayer) { this.musicPlayer = musicPlayer; } @Override public void execute() { musicPlayer.skip(); } } class StopCommand implements Command { private MusicPlayer musicPlayer; public StopCommand(MusicPlayer musicPlayer) { this.musicPlayer = musicPlayer; } @Override public void execute() { musicPlayer.stop(); } }
3.MusicInvoker(調用者),接收客戶端發送過來的指令
class MusicInvoker { private Command playCommand; private Command skipCommand; private Command stopCommand; public void setPlayCommand(Command playCommand) { this.playCommand = playCommand; } public void setSkipCommand(Command skipCommand) { this.skipCommand = skipCommand; } public void setStopCommand(Command stopCommand) { this.stopCommand = stopCommand; } public void play() { playCommand.execute(); } public void skip() { skipCommand.execute(); } public void stop() { stopCommand.execute(); } }
4.MusicPlayer(接收者),執行接收到的指令
class MusicPlayer { public void play() { System.out.println("播放..."); } public void skip() { System.out.println("跳過..."); } public void stop() { System.out.println("停止..."); } }
5.測試類MusicPlayerClient
public class MusicPlayerClient { public static void main(String[] args) { // 創建 Receiver(接收者) MusicPlayer musicPlayer = new MusicPlayer(); // Command(抽象命令類) Command playCommand = new PlayCommand(musicPlayer); Command skipCommand = new SkipCommand(musicPlayer); Command stopCommand = new StopCommand(musicPlayer); // 創建 Invoker(調用者) MusicInvoker invoker = new MusicInvoker(); invoker.setPlayCommand(playCommand); invoker.setSkipCommand(skipCommand); invoker.setStopCommand(stopCommand); // 測試 invoker.play(); invoker.skip(); invoker.stop(); invoker.play(); invoker.stop(); } }
6.運行結果
宏命令宏命令: 又稱為組合命令,組合多個命令,它是命令模式和組合模式聯用的產物;
假設MusicPlayer(音樂播放器)有一個記錄功能,可以把每一個命令記錄下來,在需要的時候又可以將歷史記錄的命令在執行一遍,這就是所謂的宏命令集功能。
UML圖如下:
1.定義MacroCommand(宏命令類),繼承基礎Command(命令類)
interface MacroCommand extends Command { void add(Command command); void remove(Command command); }
2.創建MacroMusicCommand實現MacroCommand
class MacroMusicCommand implements MacroCommand { private static final ListCOMMANDS = new ArrayList<>(); @Override public void execute() { System.out.println("==========回放開始=========="); COMMANDS.forEach(Command::execute); System.out.println("==========回放結束=========="); } @Override public void add(Command command) { COMMANDS.add(command); } @Override public void remove(Command command) { COMMANDS.remove(command); } }
3.測試類
public class MusicPlayerClient { public static void main(String[] args) { // 創建 Receiver(接收者) MusicPlayer musicPlayer = new MusicPlayer(); // Command(抽象命令類) Command playCommand = new PlayCommand(musicPlayer); Command skipCommand = new SkipCommand(musicPlayer); Command stopCommand = new StopCommand(musicPlayer); // 創建 Invoker(調用者) MacroCommand macroCommand = new MacroMusicCommand(); macroCommand.add(playCommand); macroCommand.add(skipCommand); macroCommand.add(stopCommand); // 測試 macroCommand.execute(); } }
4.運行結果
JDK中應用我們平時使用的java.lang.Runnable就是命令模式的經典應用
// 命令類 與 具體命令實現類 Runnable runnable = new Runnable() { @Override public void run() { System.out.println("關注 battcn 公眾號即可免費領取視頻"); } }; // Invoker(調用者) 接收命令 Thread thread = new Thread(runnable); // 調用 start 命令 thread.start(); // JDK8 簡化寫法 new Thread(()->System.out.println("關注 battcn 公眾號即可免費領取視頻")).start();總結
優點
將行為調用者和各種行為分隔開,降低程序的耦合,便于程序擴展;
將行為的具體實現封裝起來,客戶端無需關心行為的具體實現;
為多種行為提供統一的調用入口,便于程序對行為的管理和控制;
缺點
使用命令模式,不論命令簡單還是復雜,都需要寫一個命令類來封裝,濫用命令模式會導致系統出現過多的具體命令類;
適用場景
希望將行為請求者和行為實現者解耦,不直接打交道;
希望分離掉行為請求者一部分的責任,行為請求者只需要將命令發給調用者,不再主動的去讓行為實現者產生行為,符合單一職責原則;
希望可以控制執行的命令列表,方便記錄,撤銷/重做以及事務等功能;
希望可以將請求組合使用,即支持宏命令;
說點什么全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter12/battcn-command
個人QQ:1837307557
battcn開源群(適合新手):391619659
微信公眾號:battcn(歡迎調戲)
福利關注公眾號:battcn,回復springboot即可獲得
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70657.html
摘要:備忘錄模式常常與命令模式和迭代子模式一同使用。自述歷史所謂自述歷史模式實際上就是備忘錄模式的一個變種。在備忘錄模式中,發起人角色負責人角色和備忘錄角色都是獨立的角色。 備忘錄模式(Memento Pattern)屬于行為型模式的一種,在不破壞封裝特性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。這樣就可以將該對象恢復到原先保存的狀態。 概述 備忘錄模式又叫做快照模式(...
摘要:抽象工廠模式提供了創建一系列相互依賴對象的接口,無需指定具體類抽象工廠模式是圍繞著一個超級工廠工作,創造其它的工廠類,也被稱為工廠的工廠,這種類型的設計模式是創造性的模式,因為這種模式提供了創建對象的最佳方法之一。 工廠模式是JAVA中最常用的設計模式之一,使用工廠模式后,創建對象的時候不在將創建邏輯暴露給客戶端,而是通過實現接口的方式創建對象,這種設計模式也是對象實例化的最佳方式。 ...
摘要:適配器是將接口轉換為不同接口,而外觀模式是提供一個統一的接口來簡化接口。 外觀模式(Facade Pattern)屬于結構型模式的一種,為子系統中的一組接口提供一個統一的入口,它通過引入一個外觀角色來簡化客戶端與子系統之間的交互... 概述 外觀模式是一種使用頻率非常高的結構型設計模式,當你要為一個復雜子系統提供一個簡單接口時。子系統往往因為不斷演化而變得越來越復雜。大多數模式使用時...
摘要:構造函數參數太多錯誤的對象狀態使用模式在我們的示例中,改造下召喚師類齊天大圣孫悟空上單基石天賦戰爭雷霆瘟疫之源圖奇下路基石天賦戰陣熱誠皎月女神戴安娜中單建造者模式讓我們寫的代碼更具可讀性,可理解為建立復雜的物體。 建造者模式(Builder Pattern)屬于創建型模式的一種,將多個簡單對象構建成一個復雜的對象,構建過程抽象化,不同實現方法可以構造出不同表現(屬性)的對象,還提供了一...
摘要:策略模式使得算法可以在不影響到客戶端的情況下發生變化。下面就以一個示意性的實現講解策略模式實例的結構。抽象策略角色這是一個抽象角色,通常由一個接口或抽象類實現。優點策略模式提供了管理相關的算法族的辦法。 策略模式(Strategy Pattern)屬于對象行為型模式的一種,其用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以...
閱讀 2486·2021-10-19 11:45
閱讀 2464·2021-09-30 09:56
閱讀 1432·2021-09-30 09:47
閱讀 591·2019-08-30 15:53
閱讀 1834·2019-08-30 15:44
閱讀 584·2019-08-30 12:52
閱讀 1084·2019-08-30 11:16
閱讀 1605·2019-08-29 16:36