一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

設(shè)計模式學習筆記(十七)——Command命令模式

 skywood 2007-08-06

Command命令模式介紹:

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

 

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



      

 

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

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

Command命令模式結(jié)構(gòu):

      


 

 

定義場景:

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

代碼實現(xiàn)與結(jié)構(gòu)分析:

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

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

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

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

下面來看看代碼上的實現(xiàn):首先,我先作一個OperationCommand的例子,先做一個請求的接收者Document(也就是結(jié)構(gòu)圖中的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)各種操作(結(jié)構(gòu)圖中的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 = new Document();

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

            string strOperation = Console.ReadLine();

            Command com = null;

            ArrayList ObjectState = new ArrayList();//Record state

            while (strOperation != "Exit")

            {

                switch (strOperation.ToLower())

                {

                    case "write":

                        com = new WriteCommand(doc, ObjectState);

                        com.Excute();

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

                        break;

                    case "del":

                        com = new DeleteCommand(doc, ObjectState);

                        com.Excute();

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

                        break;

                    case "undo":

                        com = new UnDoCommand(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();

            }

        }

}

 

測試結(jié)果:

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(結(jié)構(gòu)圖中的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(結(jié)構(gòu)圖中的ConcreteCommand

class DocumentCommand : Command

    {

        private Document doc;

        private ArrayList ObjectState = new ArrayList();//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 = new Document();

            DocumentCommand com = new DocumentCommand(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();

            }

        }

    }

 

測試結(jié)果如下:

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)會重新分配一塊內(nèi)存。不修改原內(nèi)存上的內(nèi)容。如果是要保存其他的引用類型應(yīng)當注意使用深拷貝,否則,所保存的狀態(tài)對象都指向一個內(nèi)存地址,隨著狀態(tài)的改變,保存不了原有的狀態(tài)。

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

Command模式的幾個要點:

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

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

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

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

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    黄色av尤物白丝在线播放网址| 日本高清视频在线观看不卡| 亚洲一区二区三区一区| 99一级特黄色性生活片| 色鬼综合久久鬼色88| 都市激情小说在线一区二区三区| 麻豆果冻传媒一二三区| 东京热加勒比一区二区| 二区久久久国产av色| 综合久综合久综合久久| 色婷婷久久五月中文字幕| 国产精品亚洲综合天堂夜夜| 91麻豆视频国产一区二区| 日韩国产传媒在线精品| 亚洲熟女一区二区三四区| 日韩人妻精品免费一区二区三区| 黄色国产一区二区三区| 国产又粗又猛又长又黄视频| 国产视频在线一区二区| 亚洲国产香蕉视频在线观看| 日本二区三区在线播放| 午夜亚洲少妇福利诱惑| 精品日韩视频在线观看| 日韩一级一片内射视频4k| 久久精品久久久精品久久| 欧美色婷婷综合狠狠爱| 国产又粗又爽又猛又黄的| 亚洲中文字幕视频一区二区| 色哟哟哟在线观看视频| 91在线播放在线播放观看| 国产又粗又猛又大爽又黄| 视频一区二区三区自拍偷| 国产精品视频久久一区| 免费国产成人性生活生活片| 婷婷激情五月天丁香社区| 二区久久久国产av色| 熟女高潮一区二区三区| 午夜精品麻豆视频91| 91久久精品国产一区蜜臀| 在线观看中文字幕91| 98精品永久免费视频|