<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                OBSERVER 及 ITERATOR 模式 —— 知我者謂我心憂,不知我者謂我何求 junguo Observer模式的中文譯名是觀察者模式,定義是:定義對象間一種一對多的關系,當一個對象的狀態發生變化時,所有依賴它的對象都得到通知并被自動更新。COM中的連接點事實上就是一種觀察者模式,COM中的連接點主要是為過程化語言提供的,如果我們使用C++調用COM組件,那么我們可以直接利用回調函數的形式來完成同樣的功能。而事實上Observer模式的具體實現,也是通過回調函數來完成。我們還是通過例子來學習該模式。 彼黍離離,彼稷之苗。行邁靡靡,中心搖搖。知我者,謂我心憂;不知我者,謂我何求。悠悠蒼天,此何人哉! 彼黍離離,彼稷之穗。行邁靡靡,中心如醉。知我者,謂我心憂;不知我者,謂我何求。悠悠蒼天,此何人哉! 彼黍離離,彼稷之實。行邁靡靡,中心如噎。知我者,謂我心憂;不知我者,謂我何求。悠悠蒼天,此何人哉! 是從馮曉剛的《天下無賊》開始熟悉這首詩的。這首詩取自《詩經》中的《王風》,詩歌產生背景是這樣的。西周王朝的最后一位君主周幽王,是個不成器的家伙。寵愛的妃子褒姒從來不笑,為了博美人一笑,他玩了一個“烽火戲諸侯”的游戲。結果等犬戎陣來攻擊他的時候,烽火已經無法招來諸侯的救軍。他被犬戎追殺,最后葬身于驪山腳下。西周的歷史結束,繼任的周平王被迫東遷,失去了多諸侯的控制權。而后一位當時周王朝的老臣,再回西周舊都的時候,已失往日的繁華,滿目瘡痍,感傷之下,作了此詩。不過我們的例子和此詩的關系不大,我只是覺得“知我者,謂我心憂”能很好的反映Observer模式的意義。 人總是把自己的心境和周邊聯系起來,心情不好了,天空就不再是藍色的,花草也不再美麗。事實上什么也沒有變,變的只是你的心情。不過在虛擬世界里,讓世界隨著自己的心情來變,就不是困難的事情了。我們來模式這樣一個過程,當一個人的心情發生變化的時候,他所處于的天空,身邊的花木都產生相應的變化。我們來看看類圖: 從類圖可以看到,我們定義了一個觀察者接口,這個接口比較簡單。只有一個虛函數Update。而它的子類Sky和Flower也很簡單,就是實現Update。我們在看另一個接口Subject,它擁有一個Observer型的列表,用來存放所有的觀察者。它的方法包括Attach添加一個觀察者,Detach刪除一個觀察者,Notify是用來遍歷所有的觀察者,并調用它們的接口函數Update。Person是一個具體的類,事實上Subject的所有功能,都可以由它來實現。但我們應該記得一個規則:針對接口編程,而不要針對實現編程。這樣有助于我們程序的擴展。 我們來看看代碼,首先我們需要定義一個Observer的接口,而天空花木都繼承于它,代碼如下: ~~~ #ifndef __OBSERVER__H #define __OBSERVER__H //observer 接口,繼承者需要實現Update方法 class Observer { public: virtual ~Observer(){} virtual void Update(Subject* pChange) = 0; protected: Observer(){} }; //Sky類 class Sky : public Observer { private: //具體的目標對象指針,是通過它的狀態來改變觀察者的行為 //可以有多個具體的目標對象,不過這里我們提供一個 Person* m_pPerson; public: Sky(Person *pPerson) { m_pPerson = pPerson; m_pPerson->Attach(this); } virtual ~Sky() { m_pPerson->Detach(this); } void Update(Subject *pChange) { //由于可能有多個,所以這里需要判斷 if ( pChange == m_pPerson ) { if ( m_pPerson->GetSpirit() == true ) { cout << "天空是藍色的!" << endl; } else { cout << "烏云密布!" << endl; } } } }; //Flower類 class Flower : public Observer { private: Person* m_pPerson; public: Flower(Person *pPerson) { m_pPerson = pPerson; m_pPerson->Attach(this); } virtual ~Flower() { m_pPerson->Detach(this); } void Update(Subject *pChange) { if ( pChange == m_pPerson ) { if ( m_pPerson->GetSpirit() == true ) { cout << "百花燦爛時!" << endl; } else { cout << "凋零的玫瑰!" << endl; } } } }; #endif ~~~ 以上為Observer.h頭文件的內容,就是定義一個Observer接口,而后由具體的觀察者類來繼承。我們接著看看目標類的實現。 ~~~ Subject.h文件的內容: #ifndef __SUBJECT_HEADER__H #define __SUBJECT_HEADER__H //由于類Observer和Subject需要嵌套調用,所以不能直接#include"observer.h" //所以需要先申明一下 class Observer; //目標接口 class Subject { public: //添加一個觀察者 virtual void Attach(Observer *); //刪除一個觀察者 virtual void Detach(Observer *); //通知觀察者 virtual void Notify(); protected: Subject(){} private: //觀察者列表 list m_ObserverList; }; //具體的目標類 class Person : public Subject { private: bool m_bGoodSpirit; public: Person():m_bGoodSpirit(true){} bool GetSpirit(){return m_bGoodSpirit;} void GoodSpirit() { m_bGoodSpirit = true; cout << "我的心情很好,所以我看到了:" << endl; Notify(); } void BadSpirit() { m_bGoodSpirit = false; cout << "我的心情很不好,所以我看到了:" << endl; Notify(); } }; #endif ~~~ 這段代碼就是定義了一個目標類的接口。當然你也可以不使用接口,直接定義一個Person類來實現該功能,但這樣的話你在Observer的具體類的對象中就無法觀察多種對象了。 (由于此次的代碼中有嵌套使用類的情況,所以我標出了代碼所在的文件名。不熟悉該用法的話,你可以注意一下。) 我們再來看看Subject類的具體實現: 以下是Subject.cpp的文件。 ~~~ #include "Subject.h" #include "Observer.h" void Subject::Attach(Observer *pObserver) { m_ObserverList.push_back(pObserver); } void Subject::Detach(Observer *pObserver) { m_ObserverList.remove(pObserver); } void Subject::Notify() { list::iterator ite; //遍歷所有的觀察者就行通知 for( ite = m_ObserverList.begin() ; ite != m_ObserverList.end() ;++ite) (*ite)->Update(this); } ~~~ 由于嵌套使用的緣故,所以在Subject.h中無法直接使用Observer的對象,必須放到cpp中來實現,所以我們分割開來。這邊的實現其實也很簡單。我們再看看具體的使用。 ~~~ #include "Observer.h" #include "Subject.h" int main(int argc, char* argv[]) { Person p; Sky sky(&p); Flower flower(&p); p.GoodSpirit(); p.BadSpirit(); return 0; } ~~~ 運行結果如下: 在我們的例子,Observer的列表是通過C++標準庫的list來管理的,但為了講解我們的下一個模式Iterator,我們將把它變為一個數組。我們還是先來看看Iterator的定義:提供一種方法順序訪問一個聚合對象中的各個元素,而不是暴露該對象的內部表示。其實Iterator就是為我們的數組,線性表一類的容器提供一個遍歷的方法。但如今C++的標準庫中已經很好的實現了這一功能,我們應該更多的是用標準庫。在.net平臺和Java的庫中一般也都提供了很好的容器類,也都提供了迭代器。一般情況下,我們已經無需自己去實現迭代器。不過還是來簡單看看的具體實現。為了便于擴展,我們還是提供一個Iterator的接口類: ~~~ template<class Item> class Iterator { public: virtual bool hasNext() = 0; virtual Item Next() = 0; }; ~~~ 這里提供的接口比較簡單,只是判斷是否有下一個元素和返回下一個元素的操作。一般的迭代器會提供重載加號,等于號等操作,這里省略了。我對STL也不太熟悉,下一階段,準備學習一下,有時間的話,再和大家分享。 我們來實現一個數組的迭代器: ~~~ template<class Item> class ArrayIterator : public Iterator { private: //指向數組的指針 Item *m_pItems; //當前迭代器的位置 int m_iPosition; //數組的最大長度 int m_iMaxSize; public: //初始化函數 ArrayIterator(Item *pItems,int iMaxSize): m_pItems(pItems), m_iPosition(0), m_iMaxSize(iMaxSize) { } bool hasNext() { //判斷當前的元素是否有效 if ( m_iPosition < m_iMaxSize && m_pItems[m_iPosition] != NULL ) { return true; } else { return false; } } Item Next() { //返回當前的元素,并將位置加一 return m_pItems[m_iPosition++]; } }; ~~~ 也沒有什么復雜的地方。我們再來看看Subject類的實現: ~~~ //目標接口 class Subject { public: //添加一個觀察者 virtual void Attach(Observer *); //刪除一個觀察者 virtual void Detach(Observer *); //通知觀察者 virtual void Notify(); //創建迭代器 Iterator<Observer*> *CreateIterator() { return new ArrayIterator<Observer*>(m_ObserverList,10); } protected: Subject():m_iPosition(0) { for(int i = 0; i < 10 ; i++ ) m_ObserverList[i] = NULL; } private: int m_iPosition; //觀察者列表 Observer* m_ObserverList[10]; }; ~~~ 可以看到現在的Observer列表被定義成了Observer* m_ObserverList[10]。相應的我們幫它增加一個函數: ~~~ //創建迭代器 Iterator<Observer*> *CreateIterator() { return new ArrayIterator<Observer*>(m_ObserverList,10); } ~~~ 使用該函數來幫助我們生成一個迭代器。相應的我們以前用到遍歷的函數Notify就需要進行相應的修改: ~~~ void Subject::Notify() { //遍歷所有的觀察者就行通知 Iterator<Observer*> *pObserver = CreateIterator(); while( pObserver->hasNext() ) { pObserver->Next()->Update(this); } delete pObserver; } ~~~ 這里就是我們所要介紹的迭代器了。在STL中,迭代器有很好的解決方案,可以通過候捷的《STL源碼剖析》來學習。我也正準備看這本書。 好了,這講先到這兒。下次我們接著聊聊Visitor模式。 參考書目: 1, 設計模式——可復用面向對象軟件的基礎(Design Patterns ——Elements of Reusable Object-Oriented Software) Erich Gamma 等著 李英軍等譯 機械工業出版社 2, Head First Design Patterns(影印版)Freeman等著 東南大學出版社 3, 道法自然——面向對象實踐指南 王詠武 王詠剛著 電子工業出版社 4, 原來詩經可以這么讀 唐文著 河北教育出版社
                  <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>

                              哎呀哎呀视频在线观看