<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                VISITOR模式 —— 齊天大圣鬧天宮 junguo Visitor模式的中文名稱是訪問者模式,該模式的目的是提供一個類來操作其它類型中的對象結構中的元素(也就是專門幫助其它類來實現原本屬于它的函數)。它使你可以在不改變各元素類的前提下定義作用于這些元素的新操作。是不是不明白這段話的意思?沒關系,還是通過例子來理解該模式。我們先來簡述一下例子。 呵呵,好不容易想到這么個土的掉渣的例子。別見怪,我實在想不出更好的例子。例子的背景大家應該都非常熟悉,在這兒就不扯淡了。簡要描述一下我們要實現的功能。大家都知道在大鬧天宮中,有二郎神和孫悟空打斗的情節。他們兩個都有七十二變,七十二變在我們的例子里相當于七十二個方法。但他們的變化并不相同,如孫悟空變成廟的時候,尾巴變不掉,會變成一個旗桿;而二郎神沒有尾巴。所以這里把他們各自封裝。幫它們各自提供一個類。妖怪類Sprite和神仙類God看以下的類圖。 好了,有了類圖,開始開發。此次要實現的功能主要是幫助這兩個類來實現它的七十二個方法。我們知道程序肯定不是一次寫完的,每填加幾個函數,我們就想進行一下單元測試,看看自己的代碼有沒有錯誤。這時候,我們就需要重新編譯程序。由于這兩個類的方法比較多,這樣每填加一個函數,就可能需要把這整個類文件都重新編譯一次。這是件耗費時間的事,你不想看到。那么有沒有辦法幫我們解決該問題呢?有的,就是現在提到的Visitor模式。我們可以把Sprite和God的所有操作提煉成一個一個單獨的類,在這些類中完成原本屬于它們的方法。怎么做呢?先來看看類圖。 在類圖中,你可以看到我們提煉了一個新類Visitor,它有兩個子類Change1Vistor和Change2Vistor(如果有其它方法的話,我們可以添加新的類)。Visitor就是我們所說的訪問者類了,就是要通過它來幫助我們把所有的方法都提煉到單獨的類中。而Change1Vistor和Change2Vistor就是我們所要的具體類,用它來幫助我們實現神仙和妖怪的變化。我們說過了它們可能有七十二種變化,那么我們再填加新的變化的時候,就不需要去修改Sprite和God類的內容了。(當然了,如果真填加七十二中變化的話,這代碼也夠受的,估摸也好不到哪兒去,真有這樣的系統,你可能需要去尋找其它方法了。) 我們再看看我們的Sprite和God,它們擁有共同的基類SuperMan,它只有一個虛擬函數 Accept(Visitor &) ,就是通過它來實現對Visitor類的調用了。Sprite和God類各自實現該方法。為了體現Visitor的真正意義,我們給Sprite和God各自添加了成員變量,其實Visitor的目的主要是幫助處理類中的數據成員了。在后面我們將講述這個問題。好了,還是先來看看具體的代碼,所先來看Visitor的代碼: ~~~ // Visitor基類 class Visitor { public: //抽象出來針對于Sprite對象的方法 virtual void VisitorSprite(Sprite *p) = 0; //抽象出來針對God對象的方法 virtual void VisitorGod(God *p) = 0; protected: Visitor(){} }; //針對于SuperMan的第一個操作 class Change1Vistor : public Visitor { public: void VisitorSprite(Sprite *p) { cout << "這是妖怪 " << p->GetName() << " 的變化1" << endl; }; void VisitorGod(God *p) { cout << "這是神仙 " << p->GetType() <<" 的變化1" << endl; }; }; //針對于SuperMan的第一個操作 class Change2Vistor : public Visitor { public: void VisitorSprite(Sprite *p) { cout << "這是妖怪的變化2" << endl; }; void VisitorGod(God *p) { cout << "這是神仙的變化2" << endl; }; }; ~~~ 這樣,當我們有新的操作需要的時候,我們就可以重新生成一個類Change3Visitor,Change4Visitor等等,只要它們都繼承于Visitor就可以了。這樣你可以產生新的文件,而無需重新編譯以前的類文件了。 我們再來看一下SuperMan的實現: ~~~ //超人類 class SuperMan { public: virtual ~SuperMan(){} //抽象出來的調用方法的接口 virtual void Accept(Visitor &) = 0; protected: SuperMan(){} }; //妖怪類 class Sprite : public SuperMan { private: string m_strName; public: Sprite(string strName):m_strName(strName){} string GetName(){return m_strName;} void Accept(Visitor &v); }; //神仙類 class God : public SuperMan { private: string m_strType; public: God(string strType):m_strType(strType){} string GetType(){return m_strType;} void Accept(Visitor &v); }; //Sprite類的Accept實現 void Sprite::Accept(Visitor &v) { v.VisitorSprite(this); } //God類的Accept實現 void God::Accept(Visitor &v) { v.VisitorGod(this); } ~~~ 此處,我們需要注意的問題就是Accept的具體實現了。Sprite和God類需要分別調用針對于自己的接口函數。這里我們還應該考慮到一個問題,就是SuperMan的子類應該相對固定,不應該太多的變動。當它增加一個子類的時候,Visitor接口就需要變化,而相應的Visitor的所有子類也需要進行相應的變化。那么這樣與該模式的初衷節省編譯時間就背道而馳了,可能要花費更多的編譯時間。 再來看看它的使用方法: ~~~ int main(int argc, char* argv[]) { Sprite sp("孫悟空"); God g("天神,不是地府之神"); //變化1 Change1Vistor c1; sp.Accept(c1); g.Accept(c1); //變化2 Change2Vistor c2; sp.Accept(c2); g.Accept(c2); return 0; } ~~~ 我們可以看到Sprite和God對象調用相應函數的方法都可以通過Accept來實現。我們這里的實現比較簡單,只是生成了一個Sprite和一個God類,而實際應用中它可能是一個列表,數組或者是一個組合(Composite),不過原理一致。其它方式大不過就是需要遍歷所有的元素,并調用該方法。 再簡單介紹一下《設計模式》中對該模式提供的例子。在編譯器的實現過程中,會將所有源程序組合成一個語法樹。該語法樹中包括變量,賦值語句,判斷語句等內容,這些內容都是一個單獨的類,而該些類有一個統一的基類。這些類通過Composite模式組織成一個結構,也就是語法樹。 在這樣的語法樹上,可能有這樣一些操作:類型檢查,代碼優化等等,可能還有牽涉打印等,也就是操作是在不斷變化的。而樹的內容相對來說是比較固定的。這樣的話,使用Visitor就可以把這些操作獨立出來。使新的操作不至于影響原有的類。也不會使單個的類變的臃腫。 好了,這就是這次所要說的Visitor模式了。我們可以看到Visitor的初衷是為了節省編譯時間也產生的。所以也可以這么說:設計模式是開發經驗的總結,學習它的目的也就是能幫入門者更快的達到真正理解面向對象的水平。 參考書目: 1, 設計模式——可復用面向對象軟件的基礎(Design Patterns ——Elements of Reusable Object-Oriented Software) Erich Gamma 等著 李英軍等譯 機械工業出版社 2, Head First Design Patterns(影印版)Freeman等著 東南大學出版社 3, 道法自然——面向對象實踐指南 王詠武 王詠剛著 電子工業出版社
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看