• <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) 模式實現(xiàn)

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

            #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 閱讀(2226) 評論(4)  編輯 收藏 引用

            評論

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

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

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

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

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

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

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

            @xiehp@sohu.com
            這就是 it++ 和 ++it 的區(qū)別  回復(fù)  更多評論   


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            導(dǎo)航

            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            統(tǒng)計

            常用鏈接

            留言簿(18)

            隨筆分類

            隨筆檔案

            服務(wù)器編程

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            中文字幕无码久久人妻| 久久亚洲国产精品成人AV秋霞| 久久久久亚洲AV无码观看| 国产99久久精品一区二区| 囯产极品美女高潮无套久久久| 久久精品成人欧美大片| 精品久久777| 色老头网站久久网| 久久精品国产影库免费看| 色天使久久综合网天天| 国产精品久久波多野结衣| 精品多毛少妇人妻AV免费久久| 欧美激情精品久久久久久| 色综合久久综合中文综合网| 青青国产成人久久91网| 久久久无码人妻精品无码| 亚洲伊人久久成综合人影院 | 久久精品www人人爽人人| 亚洲国产天堂久久综合网站| 久久久久久精品免费看SSS| 香蕉久久影院| 亚洲七七久久精品中文国产| 国产日韩久久免费影院| 狼狼综合久久久久综合网| 久久99久久99精品免视看动漫| 2021国内精品久久久久久影院| 国产精品99久久精品爆乳| 国产精品美女久久久免费| 久久精品aⅴ无码中文字字幕不卡| 欧美日韩中文字幕久久久不卡 | 亚洲国产精品久久电影欧美| 久久天天婷婷五月俺也去| 色综合久久久久久久久五月| 精品无码久久久久国产| 中文字幕亚洲综合久久2| 久久久久久一区国产精品| 一本色道久久88—综合亚洲精品| 漂亮人妻被黑人久久精品| 精品久久久久一区二区三区| 青草影院天堂男人久久| 久久婷婷是五月综合色狠狠|