C++ 11标准简单实现观察者模式

观察者模式简单理解:被观察者的状态发生变化,观察者的行为同时也发生变化。

观察者模式的简单应用:

          1.声明被观察者对象。

          2.观察者向被观察者注册消息相应函数。

          3.观察者属性发生变化,同时注册上的观察者出发响应。

上面就是我对观察者的简单的理解,但是实际上并不只是如此。 目前有很多开源库都实现了这样的模式。譬如Qt中的connect函数,boost库中的signals2模块等等。有兴趣的朋友可以看看他们的源码。我这里只是一个简单的实现,没有非常强大的功能。

以下是我写的代码, 在vs2017上面是验证没有问题的。

#ifndef __DELEGATE_H__
#define __DELEGATE_H__
#include <iostream>
#include <list>
#include <functional>
#include <algorithm>

template <typename>
class delegate{};

template <typename R,typename ...Args>
class delegate<R(Args...)>{
    typedef std::function<R(Args...)> delegate_func;
    typedef std::list<delegate_func> func_list;

    public:
        delegate();
        delegate(const unsigned int& count);
        ~delegate();

        bool empty() const;
        bool full() const;
        unsigned int size() const;
        void resize(const int& size);
        unsigned int max_size() const;


        bool connect( delegate_func& func);
        template<typename C>
        bool connect(R(C::*func)(Args...),C* c_ptr);
        template<typename C>
        bool connect(C& mem);

        bool disconnect(delegate_func func);
        template<typename C>
        bool disconnect(R(C::*func)(Args...),C* c_ptr);
        template<typename C>
        bool disconnect(C& mem);

        bool disconnect_all();

        void emit(Args&& ...args) const;


    private:
        func_list _list;
        unsigned int _max_count;
};

template <typename R,typename ...Args>
    delegate<R(Args...)>::delegate()
        :_max_count(0)
    {
        
    }

template <typename R,typename ...Args>
    delegate<R(Args...)>::delegate(const unsigned int& count)
        :_max_count(count)
    {
    }

template <typename R,typename ...Args>
    delegate<R(Args...)>::~delegate()
    {
        _max_count = 0;
        _list.clear();
    }

template<typename R,typename ...Args>
    bool delegate<R(Args...)>::empty() const
    {
        return _list.empty();
    }


template<typename R,typename ...Args>
    unsigned int delegate<R(Args...)>::size() const
    {
        return _list.size();
    }

template<typename R,typename ...Args>
    bool delegate<R(Args...)>::full() const
    {
        return size() >= max_size() ? true : false;
    }

template<typename R,typename ...Args>
    void delegate<R(Args...)>::resize(const int& size)
    {
        this._max_count = size;
    }

template<typename R,typename ...Args>
    unsigned int delegate<R(Args...)>::max_size() const
    {
        return _max_count;
    }

template <typename R,typename ...Args>
    bool delegate<R(Args...)>::connect(delegate_func& func)
    {
        bool ret = false;
        if(!full)
        {
            _list.push_back(func);
            ret = true;
        }
        return ret;
    }

template <typename R,typename ...Args>
    template<typename C>
        bool delegate<R(Args...)>::connect(R(C::*func)(Args...), C* c_ptr)
        {
            bool ret = false;
            if(!full())
            {
                _list.push_back(std::bind(func,c_ptr,std::placeholders::_1));
                ret = true;
            }
            return ret;
        }

template <typename R,typename ...Args>
    template<typename C>
            bool delegate<R(Args...)>::connect(C& mem)
            {
                bool ret = false;
                delegate_func func = mem;
                if(!full())
                {
                    _list.push_back(func);
                    ret = true;
                }
                return ret;
            }


template <typename R,typename ...Args>
    bool delegate<R(Args...)>::disconnect(delegate_func func)
    {
        bool ret = false;
        auto itor = std::find_if(_list.begin(), _list.end(),
            [&](delegate_func& f) -> bool
        {
            delegate_func &fn = func;
            if (f && f.target<R(*)(Args...)>() == fn.target<R(*)(Args...)>())
            {
                return true;
            }
            return false;
        });
        if (itor != _list.end())
        {
            _list.erase(itor);
            ret = true;
        }
        return ret;
    }

template <typename R,typename ...Args>
    template<typename C>
        bool delegate<R(Args...)>::disconnect(R(C::*func)(Args...),C* c_ptr)
        {
            bool ret = false;
            auto itor = std::find_if(_list.begin(),_list.end(),[&](delegate_func& f)->bool{
                delegate_func fc = std::bind(func,c_ptr);

                if(f && f.target<R(*)(Args...)>() == fc.target<R(*)(Args...)>())
                {
                    return true;
                }
                return false;
            });
            if(itor != _list.end())
            {
                _list.erase(itor);
                ret = true;
            }
            return ret;
        }

template <typename R,typename ...Args>
    template<typename C>
            bool delegate<R(Args...)>::disconnect(C& mem)
            {
                bool ret = false;
                auto itor = std::find_if(_list.begin(), _list.end(),
                    [&](delegate_func& f) -> bool
                {
                    delegate_func &fn = mem;
                    if (f && f.target<R(*)(Args...)>() == fn.target<R(*)(Args...)>())
                    {
                        return true;
                    }
                    return false;
                });
                if (itor != _list.end())
                {
                    _list.erase(itor);
                    ret = true;
                }
                return ret;
            }

template<typename R,typename ...Args>
    bool delegate<R(Args...)>::disconnect_all()
    {
            bool ret = false;
            _list.clear();
            if(empty())
            {
                ret = true;
            }
            return ret;
    }

template<typename R,typename ...Args>
    void delegate<R(Args...)>::emit(Args&& ...args) const
    {
        for(auto func : _list)
        {
            try{
                func(args...);
            }
            catch(std::exception& ex)
            {
                std::cout << ex.what() << std::endl;
            }
        }
    }

#endif //__DELEGATE_H__

注意:在我写这段代码的时候,由于没有考虑的特别清楚,使用了std::list容器当作了观察者函数的载体。所以,在disconnect的时候我是使用std::function中的target来判断两个std::function对象是否相等。但是,从网上查了下资料。这样的判断并不完美,会存在错误。  所以,如果有想使用这块代码的同学们,可以使用std::unordered_map 容器来替代list容器。这里可能会有同学问我为什么不使用map容器,哈哈。虽然扯的有点远,但是我想说的是map容器会实现自动排序。这个功能我们并不需要。为了节约那么一丢丢的性能。(其实这里我想说的是写代码的时候要选择合适的)。

最后,我就不贴测试代码了, 有兴趣的可以自己写一写。

猜你喜欢

转载自blog.csdn.net/qq_15024587/article/details/83028275