在C ++中创建观察者设计模式的好方法

时间:2018-08-14 19:26:06

标签: c++ design-patterns observer-pattern

我正在尝试在C ++中实现观察者设计模式,如下所示

<httpEndpoint httpPort=9081 ... />

我正在向对象明确注册对象。这是正确的方法还是我只需要通过观察者类进行注册。上面的方法有什么问题吗?

1 个答案:

答案 0 :(得分:6)

这是在回调集合中使用lambda和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();
}