【C++11】改进观察者模式

经典的观察者模式

先看一下GOF的经典观察者模式,主题类Subject中包含的观察者的列表,并且提供attach、detach以及notify通知接口。通知后调用观察者的虚接口。

使用C++11改进

template<typename Func>
class Events
{
public:
    //注册观察者
    int connect(Func&& f)
    {
        return assgin(f);
    }

    //注册观察者
    int connect(const Func& f)
    {
        return assgin(f);
    }

    //移除观察者
    void disconnect(int key)
    {
        m_connections.erase(key);
    }

    //通知所有的观察者
    template<typename ...Args>
    void notify(Args...args)
    {
        for (auto& it : m_connections)
        {
            //入参传入所有的观察者,需要入参保存一致
            it.second(std::forward<Args>(args)...);
        }
    }

private:
    template<typename F>
    int assgin(F &&f)
    {
        int k = m_observerId++;
        m_connections.emplace(k, std::forward<F>(f));
        return k;
    }
    int m_observerId = 0;               //观察者号
    std::map<int, Func> m_connections;  //观察者列表
};

struct StA
{
    int a, b;
    void print(int a, int b)
    {
        cout << a << "," << b << endl;
    }
};

void print(int a, int b)
{
    cout << a << "," << b << endl;
}

int main()
{
    Events<std::function<void(int, int)>> myevent;

    //函数方式注册观察者
    auto key = myevent.connect(print);

    //lambda注册,修改对象数据
    StA t;
    auto lambdakey = myevent.connect([&t](int a, int b) {t.a = a; t.b = b; });

    //functional
    std::function<void(int, int)> f = std::bind(&StA::print, &t, std::placeholders::_1, std::placeholders::_2);
    myevent.connect(f);

    int a = 1, b = 2;
    myevent.notify(a, b);
    cout << t.a << "," << t.b << endl;

    getchar();
    return 0;
}

内部维护了一个泛型函数map表,这样就消除了继承导致的强耦合(需要注册的观察者对象都需要继承观察者虚基类),通知接口使用可变参数模板,消除接口变化的影响。

代码引自:深入应用C++11 代码优化与工程实践 8.2节

猜你喜欢

转载自blog.csdn.net/gx864102252/article/details/80739885