一起学设计模式 - 命令模式
命令模式(Command Pattern)屬于行為型模式的一種,又稱為行動(dòng)(Action)模式或交易(Transaction)模式。將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而達(dá)到用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化,對(duì)于排隊(duì)請(qǐng)求或請(qǐng)求日志記錄,可以提供命令的撤銷和恢復(fù)功能。
<!-- more -->
概述
命令模式:對(duì)命令的封裝,把發(fā)送命令和執(zhí)行命令的責(zé)任分割開,分別委派給不同的對(duì)象,每一個(gè)命令都是一個(gè)操作,允許請(qǐng)求方與接收方獨(dú)立開來,使之請(qǐng)求方不必清楚接收方的接口,更不必知道請(qǐng)求是怎么被接收,以及操作是否被執(zhí)行、何時(shí)被執(zhí)行,以及是怎么被執(zhí)行的。
UML結(jié)構(gòu)圖
模式結(jié)構(gòu)
- Command(抽象命令類): 聲明了用于執(zhí)行請(qǐng)求的的exceute()等方法
- ConcreteCommand(具體命令類): 抽象命令類的子類,對(duì)應(yīng)具體的接收者對(duì)象,將接收者對(duì)象的動(dòng)作綁定其中。在實(shí)現(xiàn)execute()方
法時(shí),將調(diào)用接收者對(duì)象的相關(guān)操作(Action)。
- Invoker(調(diào)用者): 調(diào)用命令對(duì)象執(zhí)行請(qǐng)求,相關(guān)的方法叫做行動(dòng)方法。
- Receiver(接收者): 負(fù)責(zé)具體實(shí)施和執(zhí)行一個(gè)請(qǐng)求。任何一個(gè)類都可以成為接收者,實(shí)施和執(zhí)行請(qǐng)求的方法叫做行動(dòng)方法。
案例
博主比較喜歡聽歌,這里就以MusicPlayer(音樂播放器)為案例,一般播放器中都有播放(play),跳過(skip),停止(stop)等功能,是一種比較典型的命令模式
UML圖如下:
1.定義Command(抽象命令類),只有一個(gè)execute()用來執(zhí)行命令
interface Command {void execute(); }2.創(chuàng)建不同指令的ConcreteCommand(具體命令類)
class PlayCommand implements Command {private MusicPlayer musicPlayer;public PlayCommand(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.play();} }class SkipCommand implements Command {private MusicPlayer musicPlayer;public SkipCommand(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.skip();} }class StopCommand implements Command {private MusicPlayer musicPlayer;public StopCommand(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.stop();} }3.MusicInvoker(調(diào)用者),接收客戶端發(fā)送過來的指令
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(接收者),執(zhí)行接收到的指令
class MusicPlayer {public void play() {System.out.println("播放...");}public void skip() {System.out.println("跳過...");}public void stop() {System.out.println("停止...");} }5.測(cè)試類MusicPlayerClient
public class MusicPlayerClient {public static void main(String[] args) {// 創(chuàng)建 Receiver(接收者)MusicPlayer musicPlayer = new MusicPlayer();// Command(抽象命令類)Command playCommand = new PlayCommand(musicPlayer);Command skipCommand = new SkipCommand(musicPlayer);Command stopCommand = new StopCommand(musicPlayer);// 創(chuàng)建 Invoker(調(diào)用者)MusicInvoker invoker = new MusicInvoker();invoker.setPlayCommand(playCommand);invoker.setSkipCommand(skipCommand);invoker.setStopCommand(stopCommand);// 測(cè)試invoker.play();invoker.skip();invoker.stop();invoker.play();invoker.stop();} }6.運(yùn)行結(jié)果
宏命令
宏命令: 又稱為組合命令,組合多個(gè)命令,它是命令模式和組合模式聯(lián)用的產(chǎn)物;
假設(shè)MusicPlayer(音樂播放器)有一個(gè)記錄功能,可以把每一個(gè)命令記錄下來,在需要的時(shí)候又可以將歷史記錄的命令在執(zhí)行一遍,這就是所謂的宏命令集功能。
UML圖如下:
1.定義MacroCommand(宏命令類),繼承基礎(chǔ)Command(命令類)
interface MacroCommand extends Command {void add(Command command);void remove(Command command); }2.創(chuàng)建MacroMusicCommand實(shí)現(xiàn)MacroCommand
class MacroMusicCommand implements MacroCommand {private static final List<Command> COMMANDS = new ArrayList<>();@Overridepublic void execute() {System.out.println("==========回放開始==========");COMMANDS.forEach(Command::execute);System.out.println("==========回放結(jié)束==========");}@Overridepublic void add(Command command) {COMMANDS.add(command);}@Overridepublic void remove(Command command) {COMMANDS.remove(command);} }3.測(cè)試類
public class MusicPlayerClient {public static void main(String[] args) {// 創(chuàng)建 Receiver(接收者)MusicPlayer musicPlayer = new MusicPlayer();// Command(抽象命令類)Command playCommand = new PlayCommand(musicPlayer);Command skipCommand = new SkipCommand(musicPlayer);Command stopCommand = new StopCommand(musicPlayer);// 創(chuàng)建 Invoker(調(diào)用者)MacroCommand macroCommand = new MacroMusicCommand();macroCommand.add(playCommand);macroCommand.add(skipCommand);macroCommand.add(stopCommand);// 測(cè)試macroCommand.execute();} }4.運(yùn)行結(jié)果
JDK中應(yīng)用
我們平時(shí)使用的java.lang.Runnable就是命令模式的經(jīng)典應(yīng)用
// 命令類 與 具體命令實(shí)現(xiàn)類 Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("關(guān)注 battcn 公眾號(hào)即可免費(fèi)領(lǐng)取視頻");} }; // Invoker(調(diào)用者) 接收命令 Thread thread = new Thread(runnable); // 調(diào)用 start 命令 thread.start(); // JDK8 簡(jiǎn)化寫法 new Thread(()->System.out.println("關(guān)注 battcn 公眾號(hào)即可免費(fèi)領(lǐng)取視頻")).start();總結(jié)
優(yōu)點(diǎn)
- 將行為調(diào)用者和各種行為分隔開,降低程序的耦合,便于程序擴(kuò)展;
- 將行為的具體實(shí)現(xiàn)封裝起來,客戶端無需關(guān)心行為的具體實(shí)現(xiàn);
- 為多種行為提供統(tǒng)一的調(diào)用入口,便于程序?qū)π袨榈墓芾砗涂刂?#xff1b;
缺點(diǎn)
- 使用命令模式,不論命令簡(jiǎn)單還是復(fù)雜,都需要寫一個(gè)命令類來封裝,濫用命令模式會(huì)導(dǎo)致系統(tǒng)出現(xiàn)過多的具體命令類;
適用場(chǎng)景
- 希望將行為請(qǐng)求者和行為實(shí)現(xiàn)者解耦,不直接打交道;
- 希望分離掉行為請(qǐng)求者一部分的責(zé)任,行為請(qǐng)求者只需要將命令發(fā)給調(diào)用者,不再主動(dòng)的去讓行為實(shí)現(xiàn)者產(chǎn)生行為,符合單一職責(zé)原則;
- 希望可以控制執(zhí)行的命令列表,方便記錄,撤銷/重做以及事務(wù)等功能;
- 希望可以將請(qǐng)求組合使用,即支持宏命令;
說點(diǎn)什么
全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter12/battcn-command
- 個(gè)人QQ:1837307557
- battcn開源群(適合新手):391619659
微信公眾號(hào):battcn(歡迎調(diào)戲)
福利
關(guān)注公眾號(hào):battcn,回復(fù)springboot即可獲得 <Spring Boot從入門到實(shí)戰(zhàn) 基礎(chǔ)實(shí)戰(zhàn)系列教程全集> 與 <2017最新spring boot 外賣實(shí)戰(zhàn)微信公眾平臺(tái)視頻教程>
總結(jié)
以上是生活随笔為你收集整理的一起学设计模式 - 命令模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CCNP路由实验---12、配置分发列表
- 下一篇: Adobe Flash Player 1