观察者模式简单理解:被观察者的状态发生变化,观察者的行为同时也发生变化。
观察者模式的简单应用:
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容器会实现自动排序。这个功能我们并不需要。为了节约那么一丢丢的性能。(其实这里我想说的是写代码的时候要选择合适的)。
最后,我就不贴测试代码了, 有兴趣的可以自己写一写。