深入理解Java設(shè)計模式之命令模式
一、什么是命令模式
命令模式是一個高內(nèi)聚的模式,其定義為:將一個請求封裝成一個對象,從而讓你使用不同的請求把客戶端參數(shù)化,對請 求排隊或者記錄請求日志,可以提供命令的撤銷和恢復(fù)功能。

在該類圖中,我們看到三個角色:
Receiver接受者角色:該角色就是干活的角色,命令傳遞到這里是應(yīng)該被執(zhí)行的Command命令角色:需要執(zhí)行的所有命令都在這里聲明Invoker調(diào)用者角色:接收到命令,并執(zhí)行命令
二、命令模式的使用場景
使用時機:當需要先將一個函數(shù)登記上,然后再以后調(diào)用此函數(shù)時,就需要使用命令模式,其實這就是回調(diào)函數(shù)。
有時候需要向某些對象發(fā)送請求,但是并不知道請求的接收者是誰,也不知道被請求的操作是什么。此時希望用一種松耦合的方式來設(shè)計程序,使得請求發(fā)送者和請求接收者能夠消除彼此之間的耦合關(guān)系
例子:拿訂餐來說,客人需要向廚師發(fā)送請求,但是完全不知道這些廚師的名字和聯(lián)系方式,也不知道廚師炒菜的方式和步驟。 命令模式把客人訂餐的請求封裝成 command 對象,也就是訂餐中的訂單對象。這個對象可以在程序中被四處傳遞,就像訂單可以從服務(wù)員手中傳到廚師的手中。這樣一來,客人不需要知道廚師的名字,從而解開了請求調(diào)用者和請求接收者之間的耦合關(guān)系
三、命令模式的優(yōu)缺點
優(yōu)點:
類間解耦:調(diào)用者角色與接收者角色之間沒有任何依賴關(guān)系,調(diào)用者實現(xiàn)功能時只需調(diào)用Command 抽象類的execute方法就可以,不需要了解到底是哪個接收者執(zhí)行??蓴U展性:Command的子類可以非常容易地擴展,而調(diào)用者Invoker和高層次的模塊Client不產(chǎn)生嚴 重的代碼耦合。命令模式結(jié)合其他模式會更優(yōu)秀:命令模式可以結(jié)合責任鏈模式,實現(xiàn)命令族解析任務(wù);結(jié)合模板方法模式,則可以減少 Command子類的膨脹問題。
缺點:
命令模式也是有缺點的,請看Command的子類:如果有N個命令,問題就出來 了,Command的子類就可不是幾個,而是N個,這個類膨脹得非常大,這個就需要讀者在項 目中慎重考慮使用。
四、命令模式的實現(xiàn)
Receiver類,知道如何實施與執(zhí)行一個與請求相關(guān)的操作,任何類都可能作為一個接受者
class Receiver
{
public void Action()
{
Console.WriteLine("執(zhí)行請求!");
}
}
Command類,用來聲明執(zhí)行操作的接口
abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
abstract public void Execute();
}
ConcreteCommand類,將一個接受者對象綁定于一個動作,調(diào)用接受者相應(yīng)的操作,以實現(xiàn)Execute。
class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver) : base(receiver)
{
}
public override void Execute()
{
receiver.Action();
}
}
Invoker類,要求該命令執(zhí)行這個請求
class Invoker
{
private Command command;
public void SetCommand(Command command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
客戶端代碼
static void Main(string[] args)
{
Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(c);
i.ExecuteCommand();
Console.Read();
}
五、總結(jié)
命令模式的意圖是將一個請求封裝成一個對象,從而使您可以用不同的請求對客戶進行參數(shù)化。
命令模式主要解決的問題是在軟件系統(tǒng)中,行為請求者與行為實現(xiàn)者通常是一種緊耦合的關(guān)系,但某些場合,比如需要對行為進行記錄、撤銷或重做、事務(wù)等處理時,這種無法抵御變化的緊耦合的設(shè)計就不太合適。
在某些場合,比如要對行為進行"記錄、撤銷/重做、事務(wù)"等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將"行為請求者"與"行為實現(xiàn)者"解耦?將一組行為抽象為對象,可以實現(xiàn)二者之間的松耦合,這是命令模式的使用場景。
系統(tǒng)需要支持命令的撤銷(Undo)操作和恢復(fù)(Redo)操作,也可以考慮使用命令模式
命令模式的實現(xiàn)過程通過調(diào)用者調(diào)用接受者執(zhí)行命令,順序:調(diào)用者→接受者→命令。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java List Object[]轉(zhuǎn)換成List T的實例
這篇文章主要介紹了Java List Object[]轉(zhuǎn)換成List T的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
java對xml節(jié)點屬性的增刪改查實現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava對xml節(jié)點屬性的增刪改查實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10
使用stream的Collectors.toMap()方法常見的問題及解決
這篇文章主要介紹了使用stream的Collectors.toMap()方法常見的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
Java的ThreadPoolExecutor業(yè)務(wù)線程池詳細解析
這篇文章主要介紹了Java線程池ThreadPoolExecutor詳細解析,任務(wù)剛開始進來的時候就創(chuàng)建核心線程,核心線程滿了會把任務(wù)放到阻塞隊列,阻塞隊列滿了之后才會創(chuàng)建空閑線程,達到最大線程數(shù)之后,再有任務(wù)進來,就只能執(zhí)行拒絕策略了,需要的朋友可以參考下2024-01-01
基于SpringBoot2.0默認使用Redis連接池的配置操作
這篇文章主要介紹了基于SpringBoot2.0默認使用Redis連接池的配置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
SpringBoot項目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決)
這篇文章主要介紹了SpringBoot項目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09
項目打包成jar后包無法讀取src/main/resources下文件的解決
本文主要介紹了項目打包成jar后包無法讀取src/main/resources下文件的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-04-04
Intellij IDEA 配置Subversion插件實現(xiàn)步驟詳解
這篇文章主要介紹了Intellij IDEA 配置Subversion插件實現(xiàn)步驟詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05

