代码之家  ›  专栏  ›  技术社区  ›  kadina

在C++中创建观测器设计模式的好方法

  •  1
  • kadina  · 技术社区  · 7 年前

    我尝试在C++中实现观测器设计模式,如下所示

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class observer
    {
        public:
            observer() = default;
            ~observer() = default;
    
            virtual void notify() = 0;
    };
    
    class subject
    {
        vector <observer *> vec;
    
        public:
            subject() = default;
            ~subject() = default;
    
            void _register(observer *obj)
            {
                vec.push_back(obj);
            }
    
            void unregister(observer *obj)
            {
                int i;
                for(i = 0; i < vec.size(); i++)
                {
                    if(vec[i] == obj)
                    {
                        cout << "found elem. unregistering" << endl;
                        vec.erase(vec.begin() + i);
                        break;
                    }
                }
    
                if(i == vec.size())
                {
                    cout << "elem not found to unregister" << endl;
                }
            }
    
            void notify()
            {
                vector <observer *>::iterator it = vec.begin();
                while(it != vec.end())
                {
                    (*it)->notify();
                    it ++;
                }
            }
    };
    
    class obsone : public observer
    {
        void notify()
        {
            cout << "in obsone notify" << endl;
        }
    };
    
    class obstwo : public observer
    {
        void notify()
        {
            cout << "in obstwo notify" << endl;
        }
    };
    
    int main()
    {
        subject sub;
    
        obsone *one = new obsone();
        obstwo *two = new obstwo();
    
        sub._register(one);   
        sub._register(two);
        sub.notify();
    
        sub.unregister(one);
        sub.notify();
    
        //delete two;
        //sub.notify();
    
        return 0;
    }
    

    我正在显式地向主题注册对象。这是正确的方法还是我只需要通过observer类注册。上述方法有什么问题吗?

    1 回复  |  直到 7 年前
        1
  •  7
  •   Cheers and hth. - Alf    7 年前

    下面是使用lambdas和 function 回调集合中的对象。

    细节可以大不相同!所以,这段代码不是这样的,只是你的代码以一种特定的方式重写,从无数的可能性中。但它希望能显示出现代C++的基本思想。

    #include <iostream>
    #include <functional>               // std::function
    #include <stdint.h>                 // uint64_t
    #include <unordered_map>            // std::unordered_map
    #include <utility>                  // std::move    
    #include <vector>                   // std::vector
    using namespace std;
    
    namespace my
    {
        using Callback = function<void()>;
        template< class Key, class Value > using Map_ = unordered_map<Key, Value>;
    
        class Subject
        {
        public:
            enum Id: uint64_t {};
    
        private:
            Map_<uint64_t, Callback> m_callbacks;
    
            static auto id_value()
                -> uint64_t&
            {
                static uint64_t the_id;
                return the_id;
            }
    
        public:
            auto add_listener( Callback cb )
                -> Id
            {
                const auto id = Id( ++id_value() );
                m_callbacks.emplace( id, move( cb ) );
                return id;
            }
    
            auto remove_listener( const Id id )
                -> bool
            {
                const auto it = m_callbacks.find( id );
                if( it == m_callbacks.end() )
                {
                    return false;
                }
                m_callbacks.erase( it );
                return true;
            }
    
            void notify_all() const
            {
                for( const auto& pair : m_callbacks )
                {
                    pair.second();
                }
            }
        };
    }
    
    struct Observer_1
    {
        void notify() { cout << "Observer_1::notify() called." << endl; }
    };
    
    struct Observer_2
    {
        void notify() { cout << "Observer_2::notify() called." << endl; }
    };
    
    auto main()
        -> int
    {
        my::Subject     subject;
        Observer_1      one;
        Observer_2      two;
    
        using Id = my::Subject::Id;
        const Id listener_id_1 = subject.add_listener( [&]{ one.notify(); } );
        const Id listener_id_2 = subject.add_listener( [&]{ two.notify(); } );
    
        cout << "After adding two listeners:" << endl;
        subject.notify_all();
        cout << endl;
    
        subject.remove_listener( listener_id_1 )
            and (cout << "Removed listener 1." << endl)
            or (cout << "Did not find registration of listener 1." << endl);
        cout << endl;
        cout << "After removing or attempting to remove listener 1:" << endl;
        subject.notify_all();
    }
    
    推荐文章