假定電視機/TV有方法open()、close()和changeChannel()用于打開、關閉和切換電視頻道,而遙控器/Controller對TV的操作,通常使用消息傳遞/方法調用表達式。
圖3-3 消息傳遞、C/S結構
命令模式則是追求一種千秋萬代一統江湖的服務請求方式。
學習命令模式稍有難度,畢竟一統江湖的事情,總得有點難度。
先直接給出命令模式的例子吧。
既然有了Command,按照多態也好,難度系數為0的策略模式也罷,tv的open()演變成Command的子類OpenCommand。
OpenCommand有私有成員TV tv,而OpenCommand的exe()干什么?顯然只需要一條語句tv.open()。代碼自己隨手寫吧。
因為我們擁有依賴注入工具tool.God,(注意:在我的博客的很多的文章中,都使用了該工具,但是類名用過FromPropertyFile、IoC、God,所在包也有所變化,懶得逐一修改相關博文了。代碼的意思很清楚,讀者自己對應修改一下),因而代碼
忽略一切細節,Controller僅依賴Command,對照的,Controller1依賴TV,和TV的現有操作/方法名。
命令模式的基本結構
①命令模式的核心,是封裝普適方法exe ()的Command。通過它及其子類,將如圖3-3所示的通常的服務請求中的請求發送者和接收者完全解耦,或者說將通常的C/S結構的C與S解耦。
C僅僅依賴于Command。而OpenCommand依賴于Command和S。
所以,我們常常說Command采用了命令模式。或許應該說 以Command同志為核心的命令模式?
②依賴于Command的各種類(不包括其子類),在《設計模式》中稱為調用者(Invoker),它們是命令的發出者。借助反射機制或依賴注入模式或依賴注入工具類tool.God,調用者可以發出Command的各種子類封裝的命令,而且不需要知道最終調用的是什么方法名、不需要知道最終誰執行。
如果調用者突發奇想地發出(需要)新的命令,可以編寫Command的新子類以及執行者。
在配置文件中添加eat =method.command.EatCommand
則修改Controller的"open",即c1 =(Command)God.create("eat");就ok。《設計模式》中,給命令模式(Command Pattern)的定義/意圖比較繁瑣。正如刀可以砍人,你把刀玩出花樣來――來個回馬刀都可以,刀的基本作用還是砍人。
我的定義是:以封裝普適方法的命令類層次為橋梁,將通常C/S結構的C與S解耦。
既然命令模式使得C僅僅依賴于Command,它不知道S為何物,也不知道S的接口,所以,
C下達的一系列命令,你可以組合成一個隊列、可以組合成一個批命令;也可以反之,將C下達的一個命令分解成若干具體的命令;
對于命令執行前后的變化加以監控,你可以實現undo或redo;如果命令只是改變一個頁面的顏色,你很容易undo/取消操作;如果命令導致手榴彈炸了一個房屋,omg,你undo就很麻煩。
你可以玩出其他花樣。比如C下達的一個命令open,對于接收者為TV,就打開電視;如果配置的接收者為一個連長,他就打開/攻占一座城門。
你可以玩出更多的花樣……
續 返回目錄