Java設(shè)計(jì)模式之命令模式CommandPattern詳解
概念
命令模式:把一個(gè)請求封裝為一個(gè)對象,從而使你可用不同的請求對客戶進(jìn)行參數(shù)化;對請求排隊(duì)或記錄請求日志,以及支持可撤銷的操作。
在軟件系統(tǒng)中,“行為請求者”與“行為實(shí)現(xiàn)者”通常呈現(xiàn)一種“緊耦合”。但在某些場合,比如要對行為進(jìn)行“記錄、撤銷/重做、事務(wù)”等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將“行為請求者”與“行為實(shí)現(xiàn)者”解耦?將一組行為抽象為對象,實(shí)現(xiàn)二者之間的松耦合。這就是命令模式(Command Pattern)
UML模式結(jié)構(gòu)分析
Command接口:
定義命令的接口,聲明執(zhí)行的方法execute()。
ConcreteCommand子類:
命令接口實(shí)現(xiàn)對象,不同命令對應(yīng)不同子類。通常具體命令類會(huì)持有接受者引用,并調(diào)用接收者的功能來完成命令要執(zhí)行 的操作。
Receiver類:
接收者,真正執(zhí)行命令的對象。任何類都可能成為一個(gè)接收者,只要它能夠?qū)崿F(xiàn)命令要求實(shí)現(xiàn)的相應(yīng)功能。
Invoker類:
要求命令對象執(zhí)行請求,通常會(huì)持有命令對象,可以持有很多的命令對象。這個(gè)是客戶端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方,也就是說相當(dāng)于使用命令對象的入口。
Client類:
創(chuàng)建具體的命令對象,并且設(shè)置命令對象的接收者。注意這個(gè)不是我們常規(guī)意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個(gè)Client稱為裝配者會(huì)更好理解,因?yàn)檎嬲褂妹畹目蛻舳耸菑腎nvoker來觸發(fā)執(zhí)行。
模式協(xié)作
- Client創(chuàng)建一個(gè)ConcreteCommand對象并指定他的Receiver對象
- 某個(gè)Invoker對象存儲(chǔ)該ConcreteCommand對象
- 該Invoker通過調(diào)用Command對象的Execute操作來提交一個(gè)請求。若該命令是可撤銷的,ConcreteCommand就在執(zhí)行Execute操作之前存儲(chǔ)當(dāng)前狀態(tài)以用于取消該命令
- ConcreteCommand對象對調(diào)用它的Receiver的一些操作以執(zhí)行該請求
實(shí)例解析
電視機(jī)是請求的接收者(Receiver),遙控器是請求的發(fā)送者(Invoker),遙控器上有一些按鈕,不同的按鈕對應(yīng)電視機(jī)的不同操作(ConcreteCommand)。抽象命令角色由一個(gè)命令接口(Command)來扮演,有三個(gè)具體的命令類實(shí)現(xiàn)了抽象命令接口,這三個(gè)具體命令類分別代表三種操作:打開電視機(jī)、關(guān)閉電視機(jī)和切換頻道。顯然,電視機(jī)遙控器就是一個(gè)典型的命令模式應(yīng)用實(shí)例。
接收者Television:
package commandpattern; public class Television { private int channel; public void turnOn() { System.out.println("The televison is on."); } public void turnOff() { System.out.println("The television is off."); } public void changeChannel(int channel) { this.channel = channel; System.out.println("Now televison channel is " + channel); } }
命令接口:
package commandpattern; public interface Command { public void execute(); }
具體命令——打開電視機(jī)CommandOn:
package commandpattern; public class CommandOn implements Command { private Television television; public CommandOn(Television television) { this.television = television; } @Override public void execute() { // TODO Auto-generated method stub television.turnOn(); } }
具體命令——切換頻道CommandChange:
package commandpattern; public class CommandChange implements Command { private Television television; private int channel; public CommandChange(Television television,int channel) { this.channel = channel; this.television = television; } @Override public void execute() { // TODO Auto-generated method stub television.changeChannel(channel); } }
具體命令——關(guān)閉電視機(jī)CommandOff:
package commandpattern; public class CommandOff implements Command { private Television television; public CommandOff(Television television) { this.television = television; } @Override public void execute() { // TODO Auto-generated method stub television.turnOff(); } }
命令發(fā)起人Invoker,這里就是遙控器Control類,它持有多種具體命令對象:
package commandpattern; public class Control { private Command onCommand, offCommand, changeCommand; public Control(Command on, Command off, Command change) { onCommand = on; offCommand = off; changeCommand = change; } public void turnOn() { onCommand.execute(); } public void turnOff() { offCommand.execute(); } public void changeChannel() { changeCommand.execute(); } }
客戶端Client,創(chuàng)建接收者,創(chuàng)建具體命令持有接收者,創(chuàng)建命令發(fā)起人持有各種具體命令。
package commandpattern; public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //命令接收者 Television television = new Television(); //命令 CommandOn on = new CommandOn(television); CommandOff off = new CommandOff(television); CommandChange change = new CommandChange(television, 4); Control control = new Control(on, off, change); //執(zhí)行命令 control.turnOn(); control.changeChannel(); control.turnOff(); } }
輸出:
The televison is on.
Now televison channel is 4
The television is off.
其實(shí)命令模式像很多設(shè)計(jì)模式一樣——通過在你的請求和處理之間加上了一個(gè)中間人的角色,來達(dá)到分離耦合的目的。通過對中間人角色的特殊設(shè)計(jì)來形成不同的模式。
當(dāng)然命令模式就是一種特殊設(shè)計(jì)的結(jié)果。
優(yōu)點(diǎn):
- 降低對象之間的耦合度。
- 新命令可以很容易地加入到系統(tǒng)中。
- 可以比較容易地設(shè)計(jì)一個(gè)組合命令。
- 調(diào)用同一方法實(shí)現(xiàn)不同功能。
缺點(diǎn):
使用命令模式可能會(huì)導(dǎo)致某些系統(tǒng)有過多的具體命令類。因?yàn)獒槍γ恳粋€(gè)命令都需要設(shè)計(jì)一個(gè)具體命令類,因此某些系統(tǒng)可能需要大量具體命令類,這將影響命令模式的使用。
到此這篇關(guān)于Java設(shè)計(jì)模式之命令模式CommandPattern詳解的文章就介紹到這了,更多相關(guān)Java命令模式CommandPattern內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringMVC使用JsonView針對統(tǒng)一實(shí)體返回不同信息
這篇文章主要為大家介紹了SpringMVC使用JsonView針對統(tǒng)一實(shí)體返回不同信息,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03Java傳值調(diào)用和傳引用調(diào)用方式(參數(shù)引用為null問題)
這篇文章主要介紹了Java傳值調(diào)用和傳引用調(diào)用方式(參數(shù)引用為null問題),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09如何使用BeanUtils.copyProperties進(jìn)行對象之間的屬性賦值
這篇文章主要介紹了使用BeanUtils.copyProperties進(jìn)行對象之間的屬性賦值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05在windows環(huán)境下安裝jdk8、jdk9、jdk11、jdk12并自由切換
這篇文章主要介紹了在windows環(huán)境下安裝jdk8、jdk9、jdk11、jdk12并自由切換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05