久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    設(shè)計(jì)模式學(xué)習(xí)筆記(十七)——Command命令模式

     skywood 2007-08-06

    Command命令模式介紹:

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

     

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



          

     

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

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

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

          


     

     

    定義場(chǎng)景:

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

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

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

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

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

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

    下面來看看代碼上的實(shí)現(xiàn):首先,我先作一個(gè)OperationCommand的例子,先做一個(gè)請(qǐng)求的接收者Document(也就是結(jié)構(gòu)圖中的Receiver

    class Document

        {

            public string strContent;

     

            public Document()

            {

                strContent = "";

            }

    }

     

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

    abstract class Command

        {

            public Command()

            { }

            public abstract void Excute();

    }

     

    接下來,就要實(shí)現(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);

            }

    }

     

    實(shí)現(xiàn)了各種操作后,編寫一個(gè)客戶代碼進(jìn)行測(cè)試

    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();

                }

            }

    }

     

    測(cè)試結(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:

     

    下面再來實(shí)現(xiàn)以下ObjectCommand的例子,首先還是編寫一個(gè)已存在的請(qǐng)求接收者Document(結(jié)構(gòu)圖中的Receiver

    class Document

        {

            public string strContent;

     

            public Document()

            {

                strContent = "";

            }

    }

     

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

    abstract class Command

        {

            public Command()

            {  }

     

            public abstract void Write();

            public abstract void Delete();

            public abstract void UnDo();

    }

     

    有了Command,就可以實(shí)現(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);

            }

    }  

     

    接下來就用一個(gè)客戶端代碼作一下測(cè)試

    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();

                }

            }

        }

     

    測(cè)試結(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:

     

    這兩個(gè)程序中需要有幾點(diǎn)說明:

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

    2、              在代碼實(shí)例中,我對(duì)狀態(tài)的保存處理相對(duì)簡(jiǎn)單,但這是因?yàn)槔昧?span lang="EN-US">String對(duì)象的特點(diǎn),當(dāng)String對(duì)象被修改時(shí),系統(tǒng)會(huì)重新分配一塊內(nèi)存。不修改原內(nèi)存上的內(nèi)容。如果是要保存其他的引用類型應(yīng)當(dāng)注意使用深拷貝,否則,所保存的狀態(tài)對(duì)象都指向一個(gè)內(nèi)存地址,隨著狀態(tài)的改變,保存不了原有的狀態(tài)。

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

    Command模式的幾個(gè)要點(diǎn):

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

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

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

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

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

      0條評(píng)論

      發(fā)表

      請(qǐng)遵守用戶 評(píng)論公約

      類似文章 更多

      主站蜘蛛池模板: 亚洲精品日韩久久精品| 午夜无码片在线观看影院A| 国产精品普通话国语对白露脸 | 亚洲日韩欧洲无码AV夜夜摸| 欧美成人精品一区二区综合| 久久精品夜夜夜夜夜久久| 国产乱妇乱子在线视频| 亚洲理论电影在线观看| 日本国产一区二区三区在线观看 | 国产乱码精品一区二区三区四川人| 亚洲成AV人片在线观高清| 国产肉丝袜在线观看| 日韩欧美群交P内射捆绑| 人妻在卧室被老板疯狂进入| 国产普通话对白刺激| 亚洲高清日韩专区精品| 久久99热只有频精品8| 欧美韩中文精品有码视频在线 | 在线天堂中文官网| 奇米网777色在线精品| 国产精品美女久久久久久麻豆| 国产成人综合在线女婷五月99播放| 亚洲另类激情专区小说图片| 被黑人伦流澡到高潮HNP动漫| 久久精品国产清自在天天线| 在线看无码的免费网站| 国产成人无码免费看视频软件| 丰满少妇被猛烈进入高清播放 | 丰满人妻一区二区三区视频53| 欧美大胆老熟妇乱子伦视频| 国产熟睡乱子伦视频在线播放 | 久久亚洲AV成人网站玖玖| 亚洲日韩日本中文在线| 国产精品午夜福利视频| 日本中文字幕亚洲乱码| 国产片AV国语在线观看手机版| 欧美性色欧美A在线图片| 午夜成人无码免费看网站| 国产成人无码区免费内射一片色欲| 中文字幕人妻精品在线| 国产欧美久久一区二区三区|