Franky's LIFE

          Anything... ...

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            53 隨筆 :: 87 文章 :: 6 評論 :: 0 Trackbacks

          Command 命令模式介紹:

          Command 命令模式是一種對象行為型模式,它主要解決的問題是:在軟件構建過程中,“行為請求者”與“行為實現(xiàn)者”通常呈現(xiàn)一種“緊耦合”的問題。如下圖:

          ?

          有時我們必須向某對象提交請求,但并不知道關于被請求的操作或請求的接受者的任何信息,此時無法抵御變化的緊耦合是不合適的。如:需要對行為進行“記錄、撤銷 / 重做、事務”等處理。我們所要做的是將依賴關系轉化,將緊耦合變?yōu)樗神詈稀t上圖的形式轉化為如下形式:



          ??????

          ?

          ?????? Command 模式通過將請求本身變成一個對象來使行為請求者可向未指定的應用對象提出請求。

          ?????? GoF 《設計模式》中說道:將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數(shù)化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。

          Command 命令模式結構:

          ??????


          ?

          ?

          定義場景:

          ?????? 現(xiàn)在來看一個場景:對于 notepad 大家都很熟悉,在我們使用 notepad 打開一個文檔之后,往往做一些操作,如;輸入字符 (Write) 、刪除前一個字符( Delete )、撤銷剛才的操作( UnDo )。現(xiàn)在我們就用 Console 程序模擬這個過程。

          代碼實現(xiàn)與結構分析:

          ?????? 在實現(xiàn)代碼前先說明實現(xiàn) Command 模式需要烤爐的一些問題:

          1、? 一個命令對象應達到何種智能程度:命令對象的能力可大可小。這樣就出現(xiàn)了兩個極端。一是:它僅確定一個接收者和執(zhí)行該請求的動作;一是:它自己實現(xiàn)所有功能,根本不需要額外的接收者對象。我給他們起了便于我方便記憶的名字,第一種叫 OperationCommand ,第二種叫 ObjectCommand 。當然只是為了便于記憶和理解,如有不理解,在代碼實現(xiàn)與結構分析最后我會再談談我的想法,如有不妥,還請多提意見,一會在下面的代碼中會分別對這兩種情況進行示范。

          2、? 支持取消和重做:為了達到這個目的 ConcreteCommand 類中要存儲額外的狀態(tài)信息。也就是上圖中 ConcreteCommand state 屬性。

          3、? 避免取消操作中過程中的錯誤積累:由于命令重復的執(zhí)行、取消執(zhí)行和重執(zhí)行的過程可能會積累錯誤,以致一個應用的狀態(tài)最終偏離初始值。這就有必要在 Command 中存入更多的信息以保證這些對象可被精確的復原。

          下面來看看代碼上的實現(xiàn):首先,我先作一個 OperationCommand 的例子,先做一個請求的接收者 Document (也就是結構圖中的 Receiver

          class Document

          ??? {

          ??????? public string strContent;

          ?

          ??????? public Document()

          ??????? {

          ??????????? strContent = "";

          ??????? }

          }

          ?

          在這個程序中我們還要定義一個抽象類Command,對于OperationCommand類型來說,它僅確定一個接收者和執(zhí)行該請求的動作。所以,在抽象類Command中,只聲明一個Excute的方法。這個方法在其子類中進行實現(xiàn)。(當然這個Command還可以定義成接口)

          abstract class Command

          ??? {

          ??????? public Command()

          ??????? { }

          ??????? public abstract void Excute();

          }

          ?

          接下來,就要實現(xiàn)各種操作(結構圖中的ConcreteCommand),代碼如下

          // 寫操作

          class WriteCommand : Command

          ??? {

          ??????? Document doc;

          ??????? ArrayList ObjectState;

          ??????? public WriteCommand(Document doc, ArrayList state)

          ??????? {

          ??????????? this.doc = doc;

          ??????????? ObjectState = state;

          ??????? }

          ?

          ??????? public override void Excute()

          ??????? {

          ??????????? doc.strContent += Console.ReadLine();

          ??????????? ObjectState.Add(doc.strContent);

          ??????? }

          ??? }

          ???

          ??? // 刪除操作

          ??? class DeleteCommand : Command

          ??? {

          ??????? Document doc;

          ??????? ArrayList ObjectState;

          ??????? public DeleteCommand(Document doc, ArrayList state)

          ??????? {

          ??????????? this.doc = doc;

          ??????????? ObjectState = state;

          ??????? }

          ?

          ??????? public override void Excute()

          ??????? {

          ??????????? doc.strContent = doc.strContent.Substring(0, doc.strContent.Length - 1);

          ??????????? ObjectState.Add(doc.strContent);

          ??????? }

          ??? }

          ?

          ??? // 撤銷操作

          ??? class UnDoCommand : Command

          ??? {

          ??????? Document doc;

          ??????? ArrayList ObjectState;

          ??????? public UnDoCommand(Document doc, ArrayList state)

          ??????? {

          ??????????? this.doc = doc;

          ??????????? ObjectState = state;

          ??????? }

          ?

          ??????? public override void Excute()

          ??????? {

          ??????????? doc.strContent = (string)ObjectState[ObjectState.Count - 2];

          ??????????? ObjectState.Add(doc.strContent);

          ??????? }

          }

          ?

          實現(xiàn)了各種操作后,編寫一個客戶代碼進行測試

          class Program

          ??? {

          ??????? static void Main(string[] args)

          ??????? {

          ??????????? Document doc = newDocument();

          ??????????? Console.WriteLine("Please Input next operation:");

          ??????????? string strOperation = Console.ReadLine();

          ??? ???????? Command com = null;

          ??????????? ArrayList ObjectState = newArrayList();//Record state

          ??????????? while (strOperation != "Exit")

          ??????????? {

          ??????????????? switch (strOperation.ToLower())

          ??????????????? {

          ??????????????????? case "write":

          ??? ????????????????????com = newWriteCommand(doc, ObjectState);

          ??????????????????????? com.Excute();

          ??????????????????????? Console.WriteLine("Write Operation:" + doc.strContent);

          ??????????????????????? break;

          ??????????????????? case "del":

          ???????????? ???????????com = newDeleteCommand(doc, ObjectState);

          ??????????????????????? com.Excute();

          ??????????????????????? Console.WriteLine("Delete Operation:" + doc.strContent);

          ??????????????????????? break;

          ??????????????????? case "undo":

          ?????????????????? ?????com = newUnDoCommand(doc, ObjectState);

          ??????????????????????? com.Excute();

          ??????????????????????? Console.WriteLine("UnDo Operation:" + doc.strContent);

          ??????????????????????? break;

          ??????????????????? default:

          ??????????????????????? Console.WriteLine("Wrong Operation:");

          ??????????????????????? break;

          ??????????????? }

          ??????????????? Console.WriteLine("Please Input next operation:");

          ??????????????? strOperation = Console.ReadLine();

          ??????????? }

          ??????? }

          }

          ?

          測試結果:

          Please Input next operation:

          write

          k

          Write Operation:k

          Please Input next operation:

          write

          i

          Write Operation:ki

          Please Input next operation:

          write

          d

          Write Operation:kid

          Please Input next operation:

          write

          d

          Write Operation:kidd

          Please Input next operation:

          del

          Delete Operation:kid

          Please Input next operation:

          undo

          UnDo Operation:kidd

          Please Input next operation:

          ?

          下面再來實現(xiàn)以下ObjectCommand的例子,首先還是編寫一個已存在的請求接收者Document(結構圖中的Receiver

          class Document

          ??? {

          ??????? public string strContent;

          ?

          ??????? public Document()

          ??????? {

          ??????????? strContent = "";

          ??????? }

          }

          ?

          接下來實現(xiàn)抽象類Command(也可以使用接口),對于ObjectCommand類型來說, 它自己實現(xiàn)所有功能,根本不需要額外的接收者對象,所以在 Command 中聲明了所有的操作

          abstract class Command

          ??? {

          ??????? public Command()

          ??????? {? }

          ?

          ??????? public abstract void Write();

          ??????? public abstract void Delete();

          ??????? public abstract void UnDo();

          }

          ?

          有了Command,就可以實現(xiàn)具體的操作類型DocumentCommand(結構圖中的ConcreteCommand

          class DocumentCommand : Command

          ??? {

          ??????? private Document doc;

          ??????? private ArrayList ObjectState = newArrayList();//Record State

          ??????? public DocumentCommand(Document doc)

          ??????? {

          ??????????? this.doc = doc;

          ??????? }

          ?

          ? ?????? public override void Write()

          ??????? {

          ??????????? Console.WriteLine("Please input an character:");

          ??????????? string strRead = Console.ReadLine();

          ??????????? doc.strContent += strRead;

          ??????????? ObjectState.Add(doc.strContent);

          ??????? }

          ?

          ???? ??? public override void Delete()

          ??????? {

          ??????????? doc.strContent = doc.strContent.Substring(0, doc.strContent.Length - 1);

          ??????????? ObjectState.Add(doc.strContent);???????????

          ??????? }

          ?

          ??????? public override void UnDo()

          ??????? {

          ??????????? doc.strContent = (string)ObjectState[ObjectState.Count - 2];

          ??????????? ObjectState.Add(doc.strContent);

          ??????? }

          }??

          ?

          接下來就用一個客戶端代碼作一下測試

          class Program

          ??? {

          ??????? static void Main(string[] args)

          ??????? {

          ??????????? Document doc = newDocument();

          ???? ??????? DocumentCommand com = newDocumentCommand(doc);

          ??????????? Console.WriteLine("Please Input next operation:");

          ??????????? string strOperation = Console.ReadLine();

          ??????????? while (strOperation != "Exit")

          ??????????? {

          ??????????????? switch (strOperation.ToLower())

          ??????????????? {

          ??????????????????? case "write":

          ??????????????????????? com.Write();

          ??????????????????????? Console.WriteLine("Write Operation:" + doc.strContent);

          ??????????????????????? break;

          ??????????????????? case "del":

          ?? ?????????????????????com.Delete();

          ??????????????????????? Console.WriteLine("Delete Operation:" + doc.strContent);

          ??????????????????????? break;

          ??????????????????? case "undo":

          ??????????????????????? com.UnDo();

          ??????????????????????? Console.WriteLine("UnDo Operation:" + doc.strContent);

          ??????????????????????? break;

          ??????????????????? default:

          ??????????????????????? Console.WriteLine("Wrong Operation:");

          ??????????????????????? break;

          ??????????????? }

          ??????????????? Console.WriteLine("Please Input next operation:");

          ??????????????? strOperation = Console.ReadLine();

          ??????????? }

          ??????? }

          ??? }

          ?

          測試結果如下:

          Please Input next operation:

          write

          Please input an character:

          k

          Write Operation:k

          Please Input next operation:

          write

          Please input an character:

          i

          Write Operation:ki

          Please Input next operation:

          write

          Please input an character:

          d

          Write Operation:kid

          Please Input next operation:

          write

          Please input an character:

          d

          Write Operation:kidd

          Please Input next operation:

          del

          Delete Operation:kid

          Please Input next operation:

          undo

          UnDo Operation:kidd

          Please Input next operation:

          ?

          這兩個程序中需要有幾點說明:

          1、????????????? 對于OperationCommand,我的理解是它所實現(xiàn)的Command只是某一個操作對于某一個接收者,所以我給它取名為OperationCommand。對于ObjectCommand,是實現(xiàn)這樣一種對象,它實現(xiàn)了請求接收者的所有操作,所以取名為ObjectCommand

          2、????????????? 在代碼實例中,我對狀態(tài)的保存處理相對簡單,但這是因為利用了String對象的特點,當String對象被修改時,系統(tǒng)會重新分配一塊內存。不修改原內存上的內容。如果是要保存其他的引用類型應當注意使用深拷貝,否則,所保存的狀態(tài)對象都指向一個內存地址,隨著狀態(tài)的改變,保存不了原有的狀態(tài)。

          3、????????????? 在對象狀態(tài)的保存上,我們可以使用Prototype模式。

          Command 模式的幾個要點:

          1、? Command 模式的根本目的在于將“行為請求者”與“行為實現(xiàn)者”解耦,在面向對象語言中,常見的實現(xiàn)手段是“將行為抽象為對象”。

          2、? 實現(xiàn) Command 接口的具體命令對象 ConcreteCommand 有時候根據(jù)需要可能會保存一些額外的狀態(tài)信息。

          3、? 通過使用 Composite 模式,可以將多個“命名”封裝為一個“復合命令” MacroCommand

          4、? Command 模式與 C# 中的 Delegate 有些類似。但兩者定義行為接口的規(guī)范有所區(qū)別: Command 以面向對象中的“接口 - 實現(xiàn)”類定義行為接口規(guī)范,更嚴格,更符合抽象原則: Delegate 以函數(shù)簽名來定義行為接口規(guī)范,更靈活,但抽象能力比較弱

          posted on 2007-03-19 21:06 Franky 閱讀(206) 評論(0)  編輯  收藏 所屬分類: IT知識
          主站蜘蛛池模板: 岐山县| 礼泉县| 柳林县| 宁化县| 二手房| 长寿区| 绿春县| 山阴县| 松滋市| 疏附县| 潞城市| 珲春市| 茶陵县| 隆回县| 平度市| 宁化县| 泽州县| 金昌市| 恩施市| 灌南县| 讷河市| 邯郸县| 永善县| 韶山市| 阜城县| 体育| 博兴县| 肃宁县| 许昌县| 涞水县| 顺昌县| 祥云县| 裕民县| 金山区| 望城县| 怀集县| 扶绥县| 甘泉县| 鹤庆县| 武山县| 六枝特区|