Java設(shè)計(jì)模式中的命令模式
編程是一門藝術(shù),大批量的改動(dòng)顯然是非常丑陋的做法,用心的琢磨寫的代碼讓它變的更美觀。
在軟件開發(fā)系統(tǒng)中,**“方法的請(qǐng)求者”與“方法的實(shí)現(xiàn)者”之間經(jīng)常存在緊密的耦合關(guān)系,這不利于軟件功能的擴(kuò)展與維護(hù)。**例如,想對(duì)方法進(jìn)行“撤銷、重做、記錄”等處理都很不方便,因此“如何將方法的請(qǐng)求者與實(shí)現(xiàn)者解耦?”變得很重要,命令模式就能很好地解決這個(gè)問題。
在現(xiàn)實(shí)生活中,命令模式的例子也很多。比如看電視時(shí),我們只需要輕輕一按遙控器就能完成頻道的切換,這就是命令模式,將換臺(tái)請(qǐng)求和換臺(tái)處理完全解耦了。電視機(jī)遙控器(命令發(fā)送者)通過按鈕(具體命令)來遙控電視機(jī)(命令接收者)。
1.命令模式的定義
命令(Command)模式:將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,使發(fā)出請(qǐng)求的責(zé)任和執(zhí)行請(qǐng)求的責(zé)任分割開。這樣兩者之間通過命令對(duì)象進(jìn)行溝通,這樣方便將命令對(duì)象進(jìn)行儲(chǔ)存、傳遞、調(diào)用、增加與管理。
2.命令模式的優(yōu)點(diǎn)與不足
命令模式的主要優(yōu)點(diǎn):
- 通過引入中間件(抽象接口)降低系統(tǒng)的耦合度。
- 擴(kuò)展性良好,增加或刪除命令非常方便。采用命令模式增加與刪除命令不會(huì)影響其他類,且滿足“開閉原則”。
- 可以實(shí)現(xiàn)宏命令。命令模式可以與組合模式結(jié)合,將多個(gè)命令裝配成一個(gè)組合命令,即宏命令。
- 方便實(shí)現(xiàn) Undo 和 Redo 操作。命令模式可以與備忘錄模式結(jié)合,實(shí)現(xiàn)命令的撤銷與恢復(fù)。
- 可以在現(xiàn)有命令的基礎(chǔ)上,增加額外功能。比如日志記錄,結(jié)合裝飾器模式會(huì)更加靈活。
命令模式缺點(diǎn):
- 可能產(chǎn)生大量具體的命令類。因?yàn)槊恳粋€(gè)具體操作都需要設(shè)計(jì)一個(gè)具體命令類,這會(huì)增加系統(tǒng)的復(fù)雜性。
- 命令模式的結(jié)果其實(shí)就是接收方的執(zhí)行結(jié)果,但是為了以命令的形式進(jìn)行架構(gòu)、解耦請(qǐng)求與實(shí)現(xiàn),引入了額外類型結(jié)構(gòu)(引入了請(qǐng)求方與抽象命令接口),增加了理解上的困難。不過這也是設(shè)計(jì)模式的通病,抽象必然會(huì)額外增加類的數(shù)量,代碼抽離肯定比代碼聚合更加難理解。
3.命令模式的實(shí)現(xiàn)思路
可以將系統(tǒng)中的相關(guān)操作抽象成命令,使調(diào)用者與實(shí)現(xiàn)者相關(guān)分離。
命令模式包含以下主要角色。
- 抽象命令類(Command)角色:聲明執(zhí)行命令的接口,擁有執(zhí)行命令的抽象方法 execute()。
- 具體命令類(Concrete Command)角色:是抽象命令類的具體實(shí)現(xiàn)類,它擁有接收者對(duì)象,并通過調(diào)用接收者的功能來完成命令要執(zhí)行的操作。
- 實(shí)現(xiàn)者/接收者(Receiver)角色:執(zhí)行命令功能的相關(guān)操作,是具體命令對(duì)象業(yè)務(wù)的真正實(shí)現(xiàn)者。
- 調(diào)用者/請(qǐng)求者(Invoker)角色:是請(qǐng)求的發(fā)送者,它通常擁有很多的命令對(duì)象,并通過訪問命令對(duì)象來執(zhí)行相關(guān)請(qǐng)求,它不直接訪問接收者。
4.命令模式的實(shí)例
場(chǎng)景介紹:滾動(dòng)的廣告牌上,根據(jù)不同季節(jié)或者條件,可能展示不同的內(nèi)容,這里顯然就是命令模式的場(chǎng)景。
public abstract class Command { /** * 抽象方法執(zhí)行 * * @return */ public abstract String execute(); } public class DiscountCommand extends Command { /** * 命令模式綁定一個(gè)固定的操作 */ private DiscountHandler handler = new DiscountHandler(); @Override public String execute() { return handler.getDiscounts(); } } public class HotCommand extends Command { /** * 命令模式綁定一個(gè)固定的操作 */ private HotHandler handler = new HotHandler(); @Override public String execute() { return handler.getHots(); } } public class NewerCommand extends Command { /** * 命令模式綁定一個(gè)固定的操作 */ private NewerHandler handler = new NewerHandler(); @Override public String execute() { return handler.getNewers(); } } public class DiscountHandler { public String getDiscounts(){ System.out.println("返回優(yōu)惠商品列表"); return "優(yōu)惠商品列表"; } } public class HotHandler { public String getHots(){ System.out.println("返回?zé)衢T商品列表"); return "熱門商品列表"; } } public class NewerHandler { public String getNewers(){ System.out.println("返回最新商品列表"); return "最新商品列表"; } } public class ListView { /** * 維持一個(gè)抽象命令對(duì)象的引用 */ private Command command; /** * 為功能鍵注入命令 * @param command */ public void setCommand(Command command) { this.command = command; } /** * 請(qǐng)求列表 */ public void getList() { System.out.print("首頁請(qǐng)求"); /*根據(jù)命令獲取結(jié)果 不同的命令得到的結(jié)果就是不一樣的*/ String result = command.execute(); System.out.println("當(dāng)前列表:"+result); } } public static void main(String[] args) { /*三個(gè)命令,代表三個(gè)請(qǐng)求*/ Command command1,command2,command3; command1 = new HotCommand(); command2 = new NewerCommand(); command3 = new DiscountCommand(); ListView listView; listView = new ListView(); listView.setCommand(command1); listView.getList(); }
5.命令設(shè)計(jì)模式應(yīng)用場(chǎng)景
命令模式通常適用于以下場(chǎng)景:
- 請(qǐng)求調(diào)用者需要與請(qǐng)求接收者解耦時(shí),命令模式可以使調(diào)用者和接收者不直接交互。
- 系統(tǒng)隨機(jī)請(qǐng)求命令或經(jīng)常增加、刪除命令時(shí),命令模式可以方便地實(shí)現(xiàn)這些功能。
- 當(dāng)系統(tǒng)需要執(zhí)行一組操作時(shí),命令模式可以定義宏命令來實(shí)現(xiàn)該功能。
- 當(dāng)系統(tǒng)需要支持命令的撤銷(Undo)操作和恢復(fù)(Redo)操作時(shí),可以將命令對(duì)象存儲(chǔ)起來,采用備忘錄模式來實(shí)現(xiàn)。
到此這篇關(guān)于Java設(shè)計(jì)模式中的命令模式的文章就介紹到這了,更多相關(guān)Java命令模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
為什么SpringMVC中請(qǐng)求的body不支持多次讀取
這篇文章主要介紹了為什么SpringMVC中請(qǐng)求的body不支持多次讀取,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12解決@Test注解在Maven工程的Test.class類中無法使用的問題
這篇文章主要介紹了解決@Test注解在Maven工程的Test.class類中無法使用的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運(yùn)行
這篇文章主要介紹了Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運(yùn)行,在本節(jié)示例中,我們將創(chuàng)建兩個(gè)線程,一個(gè)是普通線程,向隊(duì)列中寫入事件,另外一個(gè)是守護(hù)線程,清除隊(duì)列中的事件,需要的朋友可以參考下2014-12-12Java開發(fā)SSM框架微信支付的實(shí)現(xiàn)
這篇文章主要介紹了Java開發(fā)SSM框架微信支付的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10Java?生成透明圖片的設(shè)置實(shí)現(xiàn)demo
這篇文章主要為大家介紹了Java?生成透明圖片的設(shè)置實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02自制Java工具實(shí)現(xiàn)翻譯鼠標(biāo)選中文本
這篇文章主要為大家詳細(xì)介紹了如何自制Java工具實(shí)現(xiàn)ctrl+c+c翻譯鼠標(biāo)選中文本,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2024-01-01Mybatis空值關(guān)聯(lián)的問題解析及解決方案
這篇文章給大家介紹了Mybatis空值關(guān)聯(lián)的問題解析及解決方案,文中通過代碼示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-01-01SpringBoot實(shí)現(xiàn)文件下載的限速功能
在SpringBoot項(xiàng)目中,實(shí)現(xiàn)文件下載的限速功能可以有效控制服務(wù)器帶寬的占用,并防止單個(gè)用戶消耗過多的資源,本文將通過具體的代碼示例和詳細(xì)的流程解釋,介紹如何在SpringBoot項(xiàng)目中實(shí)現(xiàn)文件下載的限速功能,需要的朋友可以參考下2024-07-07