<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文通過解決老王經常搞錯借書人的問題,來引出行為型模式中的命令模式。為了在案例之上理解的更加透徹,我們需要了解命令模式在原始碼中的應用。最後指出命令模式的應用場景和優缺點。
讀者可以拉取完整程式碼到本地進行學習,實現程式碼均測試通過後上傳到碼雲。
老王的書房藏書越來越多,每天來借書的人絡繹不絕。每天有人借書、還書、老王將A借的書算到B頭上的烏龍事件頻出。老王和小王就商量著手解決這個問題。
小王提議,在老王和借書者之間再增加一個“記錄員”角色,記錄員只管報名字就行了,具體是借什麼書由借書者自己決定就好了。
老王說:這能解決部分問題。但在真實的場景下,不可能來一個借書者“記錄員”就跑一趟。而且借書者有時候會借一半臨時有事就不借了。這些問題你也要考慮進去。
老王接著說:你應該,在“記錄員”角色中,增加一個佇列,將所有借書者都放到一個佇列中,既有往佇列中放命令的方法,也有從命令中移除的方法,方便“記錄員”請求排隊和“復原”。
老王提出來的正是命令模式的“白話文解釋”。我們來看命令模式的官方概念:將一個請求封裝為一個物件,使發出請求的責任和執行請求的責任分割開,解耦合。這樣兩者之間通過命令物件進行溝通,這樣方便將命令物件進行儲存、傳遞、呼叫、增加與管理。
在命令模式中有三個角色:
抽象命令類(Command)角色: 定義命令的介面,宣告執行的方法。
實現者/接收者(Receiver)(老王)角色: 接收者,真正執行命令的物件。任何類都可能成為一個接收者,只要它能夠實現命令要求實現的相應功能。
具體命令(Concrete Command)(記錄員)角色:具體的命令,實現命令介面;通常會持有接收者,並呼叫接收者的功能來完成命令要執行的操作。
我們基於概念和角色劃分,實現程式碼:
抽象命令類:
/** * 抽象命令類 * @author tcy * @Date 25-08-2022 */ public interface AbstractCommand { //只需要定義一個統一的執行方法 void execute(); }
具體命令角色(老王):
/** * 具體命令 * @author tcy * @Date 25-08-2022 */ public class ConcreteCommand implements AbstractCommand { //持有接受者物件 private String clent; public ConcreteCommand(String clent){ this.clent = clent; } @Override public void execute() { System.out.println("具體執行者角色(老王):"+clent+"借書..."); } }
接收者(記錄員):
/** * 接收者 * @author tcy * @Date 25-08-2022 */ public class ReceiverCommand { //可以持有很多的命令物件 private ArrayList<AbstractCommand> commands; public ReceiverCommand() { commands = new ArrayList(); } public void setCommand(AbstractCommand cmd){ commands.add(cmd); } public void removeCommand(AbstractCommand cmd){ commands.remove(cmd); } // 發出命令 public void borrowBookMeaaage() { System.out.println("接受者角色(記錄員):有人來借書啦..."); //通知全部命令 for (int i = 0; i < commands.size(); i++) { AbstractCommand cmd = commands.get(i); if (cmd != null) { cmd.execute(); } } } }
使用者端(借書者):
/** * @author tcy * @Date 25-08-2022 */ public class Client { public static void main(String[] args) { //建立接收者 //將訂單和接收者封裝成命令物件 ConcreteCommand cmd1 = new ConcreteCommand( "A"); ConcreteCommand cmd2 = new ConcreteCommand( "B"); //建立具體命令者 ReceiverCommand invoker = new ReceiverCommand(); invoker.setCommand(cmd1); invoker.setCommand(cmd2); //喊一聲有人要借書 invoker.borrowBookMeaaage(); } }
基於命令模式實現的程式碼就實現了,但是看懂程式碼是一回事,自己能寫出來就是另外一回事了。讀者最好根據案例重新仿寫一遍。
在原始碼中使用命令模式的典型案例就是Jdk多執行緒章節中的Runnable ,Runnable 相當於命令模式中的抽象命令角色。Runnable 中的 run() 方法就當於 execute() 方法。
我們知道,Java中一個類實現Runnable 介面,那麼該類就認為是一個執行緒,就相當於命令模式中的具體命令角色。
當我們呼叫start()方法後,就可以與別的執行緒強佔CPU的資源,在佔用CPU的執行緒中就會執行run()方法。CPU的排程者就相當於具體命令角色也即記錄員。Runnable 就完美的實現了使用者自定義執行緒和CPU的解耦合。
命令模式在Runnable 中的應用應該很好理解。
優點很明顯,解耦了命令請求與實現,很容易的可以增加新命令,支援命令佇列。
但是,這樣會不可避免的使具體命令類過多,增加了理解上的困難。
設計模式學到這種程度,我們就會發現設計模式不是一種單一的技術,而是各種技術的綜合體。
我們在學習設計模式的時候一定不要僅侷限於一種模式,而是站在一定的高度去整體衡量哪種設計模式才是最優的。
有時候我們會發現,使用設計模式會讓我們的程式碼變得更加的複雜,但以自己目前的開發經驗又不能確定是否採用設計模式是一個好的選擇。
歸根結低,還是我們對設計模式掌握的不夠熟練,這就需要我們繼續深入學習設計模式,當我的學完再回頭看這些問題,就很自然的迎刃而解了。
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對it145.com的支援。如果你想了解更多相關內容請檢視下面相關連結
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45