設計模式學習筆記(十四)—Command模式

          Posted on 2007-12-05 13:23 flustar 閱讀(1405) 評論(0)  編輯  收藏 所屬分類: Design Patterns

          一、 Command模式定義:
          將一個請求封裝為一個對象,從而使你不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。
          二、 模式解說
          Commad模式是一種對象行為模式,它可以對發送者(sender)和接收者(receiver)完全解耦(decoupling)。("發送者" 是請求操作的對象,"接收者" 是接收請求并執行某操作的對象。有了 "解耦",發送者對接收者的接口一無所知。)這里,"請求"(request)這個術語指的是要被執行的命令。Command模式還讓我們可以對 "何時" 以及 "如何" 完成請求進行改變。因此,Command模式為我們提供了靈活性和可擴展性。
          三、 結構圖
          Command模式結構圖如下:
           
          四、 怎么使用?
          1) 定義一個Command接口,接口中有一個統一的方法,這就是將請求/命令封裝為對象。
          2) 定義具體不同命令類ConcreteCommand實現Command接口。
          3) 定義一個命令的調用角色Invoker。
          4) 定義一個命令執行狀態的接收者Receiver(非必須)。
          五、 一個例子
          class Document{
           public void display(){
            System.out.println("顯示文檔內容");
           }
           public void undo(){
            System.out.println("撤銷文檔內容");
           }
           public void redo(){
            System.out.println("重做文檔內容");
           }
          }
          interface DocumentCommand{
           public void execute();
          }
          class DisplayCommand implements DocumentCommand{
           private Document document;
           public DisplayCommand(Document doc){
            document=doc;
           }
           public void execute() {
            
            document.display();
           }
           
          }
          class UndoCommand implements DocumentCommand{
              private Document document;
              public UndoCommand(Document doc){
               document=doc;
              }
           public void execute() {
            document.undo();
            
           }
           
          }
          class RedoCommand implements DocumentCommand{
           private Document document;
           public RedoCommand(Document doc){
            document=doc;
           }
           public void execute(){
            document.redo();
           }
          }
          class DocumentInvoker{
           private DisplayCommand _dcmd;
           private UndoCommand _ucmd;
           private RedoCommand _rcmd;
           public DocumentInvoker(DisplayCommand dcmd,UndoCommand ucmd,RedoCommand rcmd){
            this._dcmd=dcmd;
            this._ucmd=ucmd;
            this._rcmd=rcmd;
           }
           public void display(){
            _dcmd.execute();
           }
           public void undo(){
            _ucmd.execute();
           }
           public void redo(){
            _rcmd.execute();
           }
          }
          public class CommandTest {

           public static void main(String[] args) {
            Document doc=new Document();
            DisplayCommand display=new DisplayCommand(doc);
            UndoCommand undo=new UndoCommand(doc);
            RedoCommand redo=new RedoCommand(doc);
            DocumentInvoker invoker=new DocumentInvoker(display,undo,redo);
            invoker.display();
            invoker.undo();
            invoker.redo();

           }

          }
          六、 適用性
          1) 使用命令模式作為"CallBack"在面向對象系統中的替代。"CallBack"講的便是先將一個函數登記上,然后在以后調用此函數。
          2) 需要在不同的時間指定請求、將請求排隊。一個命令對象和原先的請求發出者可以有不同的生命期。換言之,原先的請求發出者可能已經不在了,而命令對象本身仍然是活動的。這時命令的接收者可以是在本地,也可以在網絡的另外一個地址。命令對象可以在串形化之后傳送到另外一臺機器上去。
          3) 系統需要支持命令的撤消(undo)。命令對象可以把狀態存儲起來,等到客戶端需要撤銷命令所產生的效果時,可以調用undo()方法,把命令所產生的效果撤銷掉。命令對象還可以提供redo()方法,以供客戶端在需要時,再重新實施命令效果。
          4) 如果一個系統要將系統中所有的數據更新到日志里,以便在系統崩潰時,可以根據日志里讀回所有的數據更新命令,重新調用Execute()方法一條一條執行這些命令,從而恢復系統在崩潰前所做的數據更新。
          七、 優缺點
          1) 優點: Command模式將 "調用操作的對象"(DocumentInvoker)和 "知道如何執行操作的對象" (Document)完全分離開來。這帶來了很大的靈活性:發送請求的對象只需要知道如何發送;它不必知道如何完成請求。
          2) 會導致某些系統有過多的具體命令類。
          八、 參考
          http://www.1-100.org/JSP/13170.htm
          http://terrylee.cnblogs.com/archive/2006/07/17/Command_Pattern.html
          http://www.jdon.com/designpatterns/command.htm
          http://www.cnblogs.com/zhenyulu/articles/69858.html


           

          posts - 146, comments - 143, trackbacks - 0, articles - 0

          Copyright © flustar

          主站蜘蛛池模板: 武穴市| 瓮安县| 金塔县| 广水市| 荆州市| 元阳县| 乌兰县| 申扎县| 前郭尔| 宜宾市| 祁门县| 临夏县| 大方县| 新田县| 罗源县| 邯郸县| 洛南县| 金华市| 城步| 南江县| 南开区| 临高县| 高雄县| 龙泉市| 西林县| 保亭| 连南| 娱乐| 鸡东县| 富顺县| 静宁县| 阿克苏市| 新乡县| 修水县| 望奎县| 扎鲁特旗| 浑源县| 毕节市| 临澧县| 林西县| 固原市|