• <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 閱讀(2219) 評論(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 的區別  回復  更多評論   

            導航

            <2007年9月>
            2627282930311
            2345678
            9101112131415
            16171819202122
            23242526272829
            30123456

            統計

            常用鏈接

            留言簿(18)

            隨筆分類

            隨筆檔案

            服務器編程

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            精品久久人人爽天天玩人人妻| 狠狠色丁香久久婷婷综合五月| 久久亚洲综合色一区二区三区| 亚洲国产精品久久久久网站| 久久综合精品国产一区二区三区| 久久91精品国产91久| 国产精品青草久久久久婷婷| 婷婷久久综合九色综合绿巨人| 狼狼综合久久久久综合网| 久久无码国产| 2020最新久久久视精品爱| 99精品久久久久久久婷婷| 999久久久国产精品| 久久久久高潮毛片免费全部播放| 久久久久九九精品影院| 九九精品99久久久香蕉| 久久亚洲精品国产精品婷婷| 91精品国产91久久| 精品无码久久久久久尤物| 97精品伊人久久大香线蕉| 国产69精品久久久久9999| 久久99亚洲网美利坚合众国| 亚洲中文字幕无码久久综合网| 久久精品二区| 国内精品欧美久久精品| 久久久久国产精品| 久久国产乱子精品免费女| 久久99精品国产麻豆| 77777亚洲午夜久久多喷| 2021最新久久久视精品爱| 久久97久久97精品免视看| 欧美激情精品久久久久| 国产午夜福利精品久久2021| 潮喷大喷水系列无码久久精品| 久久久久免费看成人影片| 久久香蕉超碰97国产精品| 亚洲午夜久久久影院伊人| 久久久噜噜噜www成人网| 狠狠久久亚洲欧美专区| 91精品日韩人妻无码久久不卡 | 久久九九精品99国产精品|