• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            eXile 的專欄

            觀察者 (Subject/Observer) 模式實現

              以前我曾經實現過觀察者模式(signal / slot )。有位朋友不以為然,也把他的實現發給我。這是用純OO的方式實現的,沒有使用模板,不依賴于其它庫。應該是仿Java或C#接口。設計得不錯,具有以下特點:
              1)當Subject或Observer 銷毀時,連接自動斷開(注冊自動取消),當然,這也是實現該模式的重點。
              2)考慮了以下因素:一個Subject是否允許多個Observer觀察?一個Observer是否允許同時觀察多個Subject? 由此可分為一對一,一對多,多對多,一般的GUI庫中都是后兩種情況,但自己寫的程序中卻第一種情況居多。所以他出于效率,設計了SimpleSubject和SimpleObserver。
              
              不足之處如下:
              1)Observer::update()只能帶無類型的參數(好象也沒有更好的辦法)。
              2)由于C++中沒有匿名類,所以使用起來并沒有Java中方便。于是我又添加了一個ObserverAdapter。

              使用舉例:


            class A : 
            public Subject
            {
                    int value;
            public:
               void setValue(
            int v)
               {
                   value 
            = v;
                   notify(
            &value);
               }       
            };

            class B : 
            public Observer
            {
            public:
               void update(void
            * arg)
               {
                   printf(
            "A changed:%d"*(int*)arg);
               }       
            };

            void f(A
            * a, B* b)
            {
                a
            ->connect(b);
                a
            ->setValue(1); 
            }

            使用ObserverAdapter ,則變成了以下情況:
            class B 
            {
               ObserverAdapter
            <B> observerOfA;
            public:
               B(A
            * a) : observerOfA(this, &B::valueChanged)
               {
                   a
            ->connect(&observerOfA);
               }

               void valueChanged(void
            * arg)
               {
                   printf(
            "A changed:%d"*(int*)arg);
               }       
            };


              代碼分為兩個文件:IObserver.h 和 Observer.h,就貼在下面吧:

            IObserver.h  : 接口定義

            #pragma once

            class ISubject;

            class IObserver 
            {
            public:
                IObserver()  {}
                virtual ~IObserver() {};

                virtual void update(void
            *= 0;
                
            protected:
                virtual void addSubject(ISubject
            * ) = 0;
                virtual void removeSubject(ISubject
            * ) = 0

                friend class ISubject;
                
            private:
                IObserver(IObserver 
            const&);
                IObserver
            & operator= (IObserver const&);
            };

            class ISubject 
            {
            public:
                ISubject() {}
                virtual ~ISubject() {};

                virtual void connect(IObserver
            *= 0;
                virtual void disconnect(IObserver
            *= 0;
                virtual bool isConnected(IObserver
            *const= 0;
                virtual void notify(void
            *= 0;

            protected:
                void addObserver(IObserver
            * observer);
                void removeObserver(IObserver
            * observer);

            private:
                ISubject(ISubject 
            const&);
                ISubject
            & operator= (ISubject const&);
            };


            Observer.h  : 具體實現

            #pragma once

            #include 
            <cassert>
            #include 
            <set>

            #include 
            "IObserver.h"

            //-------------------------------------------------------------------

            inline void ISubject::addObserver(IObserver
            * observer)
            {
                observer
            ->addSubject(this);
            }

            inline void ISubject::removeObserver(IObserver
            * observer)
            {
                observer
            ->removeSubject(this);
            }

            //-------------------------------------------------------------------

            class SimpleSubject : 
            public ISubject
            {
            public:
                SimpleSubject() : m_observer(
            0)
                {
                }
                
                ~SimpleSubject()
                {
                    
            if (m_observer) removeObserver(m_observer);
                }
                
                virtual void connect(IObserver
            * observer)
                {
                    assert(observer);
                    
            if (m_observer)
                        removeObserver(m_observer);
                    addObserver(observer);
                    m_observer 
            = observer;
                }
                
                virtual void disconnect(IObserver
            * observer)
                {
                    assert(observer 
            && observer == m_observer);
                    removeObserver(m_observer);
                    m_observer 
            = 0;
                }

                virtual bool isConnected(IObserver
            * observer) const
                {
                    return observer 
            == m_observer;
                }

                virtual void notify(void
            * arg)
                {
                    
            if (m_observer) m_observer->update(arg);
                }
                
            private:
                IObserver
            *  m_observer;
                
            };

            //-------------------------------------------------------------------

            class Subject : 
            public ISubject
            {
            public:
                Subject() : m_observers()
                {
                }
                
                ~Subject()
                {
                    std::
            set<IObserver*>::iterator
                        it 
            = m_observers.begin(),
                        e  
            = m_observers.end();
                    
            for (; it != e; ++it)
                    {
                        removeObserver(
            *it);
                    }
                }
                
                virtual void connect(IObserver
            * observer)
                {
                    assert(observer);
                    addObserver(observer);
                    m_observers.insert(observer);
                }
                
                virtual void disconnect(IObserver
            * observer)
                {
                    assert(observer);
                    removeObserver(observer);
                    m_observers.erase(observer);
                }

                virtual bool isConnected(IObserver
            * observer) const
                {
                    return m_observers.find(observer) !
            = m_observers.end();
                }

                virtual void notify(void
            * arg)
                {
                    std::
            set<IObserver*>::iterator
                        it 
            = m_observers.begin(),
                        e  
            = m_observers.end();
                    
            while (it != e)
                    {
                        (
            *it++)->update(arg); // observer can be disconnected in update()
                    }
                }
                
            private:
                std::
            set<IObserver*>  m_observers;
                
            };

            //-------------------------------------------------------------------

            class SimpleObserver  : 
            public IObserver
            {
            public:
                SimpleObserver() : m_subject(
            0)
                {
                }
                
                ~SimpleObserver()
                {
                    
            if (m_subject) m_subject->disconnect(this);
                }

                ISubject
            * getSubject() const
                {
                    return m_subject;
                }
                
            private:
                virtual void addSubject(ISubject
            * subject)
                {
                    
            if (m_subject) m_subject->disconnect(this);
                    m_subject 
            = subject;
                }

                virtual void removeSubject(ISubject
            * subject)
                {
                    assert(subject 
            == m_subject);
                    m_subject 
            = 0;
                }

            private:
                ISubject
            *   m_subject;
            };


            //-------------------------------------------------------------------

            class Observer : 
            public IObserver
            {
            public:
                Observer() : m_subjects()
                {
                }
                
                ~Observer()
                {
                    std::
            set<ISubject*>::iterator
                        it 
            = m_subjects.begin(),
                        e  
            = m_subjects.end();
                    
            while (it != e)
                    {
                        (
            *it++)->disconnect(this);
                    }
                }
                
            private:
                virtual void addSubject(ISubject
            * subject)
                {
                    assert(subject);
                    m_subjects.insert(subject);
                }
                
                virtual void removeSubject(ISubject
            * subject)
                {
                    assert(subject);
                    m_subjects.erase(subject);
                }

            private:
                std::
            set<ISubject*>   m_subjects;
            };

            //-------------------------------------------------------------------

            template 
            <class T, class Base = SimpleObserver>
            class ObserverAdapter  : 
            public Base
            {
            public:
                ObserverAdapter(T
            * t, void (T::*f)(void*))
                 : m_obj(t), m_func(f)
                {
                }

                virtual void update(void
            * arg)
                {
                    (m_obj
            ->*m_func)(arg);
                }
                
            private:
                T
            *  m_obj;
                void (T::
            *m_func)(void*);
            };

            //-------------------------------------------------------------------

            posted on 2007-09-16 11:30 eXile 閱讀(2218) 評論(4)  編輯 收藏 引用

            評論

            # re: 觀察者 (Subject/Observer) 模式實現 2007-09-17 23:40 eXile

            發現這種設計還有兩個優點:
            (1)observer雖然用于解藕很不錯,但是在C++中,最大的問題是容易出現懸掛指針,而且出現后不易調試。這個實現在這一方面做得很不錯,可以最大限度的防止這類問題的出現。
            (2)由于定義了抽象接口,很容易擴充為線程安全的實現  回復  更多評論   

            # re: 觀察者 (Subject/Observer) 模式實現 2007-09-17 23:48 eXile

            至于Observer::update(void*)可以利用ObserverAdapter實現接口強制,再利用 std::tr1::tuple 之類的來彌補類型信息的不足  回復  更多評論   

            # re: 觀察者 (Subject/Observer) 模式實現 2007-09-26 13:28 xiehp@sohu.com

            不知道你的注釋
            // observer can be disconnected in update()
            依據從何而來
            我覺得如果concrete observer 重載update()并在里面調用了disconnected時,你的程序一樣會崩潰。因為在循環中的Observer 中的std::set<ISubject*> m_subjects;
            已經發生了變化,而notify()里面的update循環仍然在繼續。。。  回復  更多評論   

            # re: 觀察者 (Subject/Observer) 模式實現[未登錄] 2007-09-26 14:33 eXile

            @xiehp@sohu.com
            這就是 it++ 和 ++it 的區別  回復  更多評論   

            導航

            <2009年1月>
            28293031123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統計

            常用鏈接

            留言簿(18)

            隨筆分類

            隨筆檔案

            服務器編程

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久亚洲美女精品国产精品| 国产精品久久久天天影视香蕉| 伊人热热久久原色播放www| 性高朝久久久久久久久久| 波多野结衣久久一区二区| 日韩AV无码久久一区二区| 青青国产成人久久91网| 欧美日韩精品久久久久| 精品久久久无码人妻中文字幕豆芽| 亚洲精品高清久久| 久久亚洲sm情趣捆绑调教| 97久久精品人人澡人人爽| 久久久www免费人成精品| 国产成人久久777777| 伊人久久综合精品无码AV专区| 亚洲国产成人久久综合一| 99久久国产亚洲综合精品| 狠狠色丁香婷婷综合久久来来去| 亚洲va国产va天堂va久久| 欧美日韩中文字幕久久久不卡 | 亚洲精品国产成人99久久| 久久久久久国产精品无码下载| 日本精品久久久中文字幕| 亚洲乱码中文字幕久久孕妇黑人| 久久一区二区三区99| 香港aa三级久久三级| 国产精品久久久久…| 久久人人爽人人爽人人片AV高清| 久久国产午夜精品一区二区三区| 99久久婷婷国产综合亚洲| 人妻无码αv中文字幕久久| 久久久久久久久久久| 久久这里都是精品| 亚洲精品视频久久久| 欧美亚洲另类久久综合婷婷| 人妻无码久久精品| 久久精品国产精品亚洲| 久久久久久青草大香综合精品| 久久天天躁狠狠躁夜夜2020老熟妇| 国产福利电影一区二区三区,免费久久久久久久精 | 久久综合国产乱子伦精品免费|