和单例模式面临的是同样的问题,主题更新的接口难以统一,很难做出一个通用的观察者模式,还是用到可变模板参数解决这个问题,其次还用到了右值引用,避免多余的内存移动。c++11版本的观察者模式支持注册的观察者为函数、函数对象和lamda表达式,也避免了虚函数调用,更简洁更通用。直接看代码。

template<typename Func>
class Events
{
public:
Events():m_nextKey(0)
{}
~Events(){}

int Connect(Func&& f)
{
return Assgin(f);
}

int Connect(Func& f)
{
return Assgin(f);
}

template<typename F>
int Assgin(F&& f)
{
int k=m_nextKey++;
m_connections[k]=f;
return k;
}

	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:
int m_nextKey;
std::map<int, Func> m_connections;
};

测试代码:

struct stA { int a, b; };
void print(int a, int b) { cout << a << ", " << b << endl; }
void TestObserver()
{
Events<std::function<void(int,int)>> myevent; auto key=myevent.Connect(print); //以函数方式注册观察者
stA t;
auto lambdakey=myevent.Connect([&t](int a, int b){ t.a=a; t.b=b; });//lamda注册 int a=1,b=2;
myevent.Notify(a,b); //广播所有观察者
myevent.Disconnect(key); //移除观察者 }

/**********************更新,增加+=和-=运算符重载,使用法和c#的event的用法接近。

#include <map>
template<typename Func>
class Events : NonCopyable
{
public:
Events() :m_nextKey()
{}
~Events(){} int operator += (Func&& f)
{
return Connect(std::forward<Func>(f));
} int operator += (Func& f)
{
return Connect(f);
} template<typename... Args>
void operator()(Args&&... args)
{
Notify(std::forward<Args>(args)...);
} Events& operator -= (int key)
{
Disconnect(key);
return *this;
} void Clear()
{
m_connections.clear();
} private:
int Connect(Func&& f)
{
return Assgin(std::forward<Func>(f));
} int Connect(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)...);
}
} template<typename F>
int Assgin(F&& f)
{
int index = m_nextKey++;
Push(index, std::forward<Func>(f));
return index;
} template<typename F>
void Push(int index, F&& f)
{
m_connections.emplace(index, std::move(f));
} template<typename F>
void Push(int index, F& f)
{
m_connections.emplace(index, f);
} private:
int m_nextKey;
std::map<int, Func> m_connections;
};

测试代码:

struct stA {
int a;
int b;
void fun(int x, int y)
{
a = x;
b = y;
cout << "a = " << a << " b= " << b << endl;
}
};
void print(int a, int b) { cout << a << ", " << b << endl; }
void TestEvent()
{
using Delegate1 = std::function<void(int, int)>;
using Event1 = Events<Delegate1>;
Event1 evnet1;
  //添加委托
stA t;
auto key1 = evnet1 += &print;
auto key2 = evnet1 += [&t](int a, int b){
t.a = a;
t.b = b;
cout << "t.a = " << t.a << " t.b = " << t.b << endl;
};
auto key3 = evnet1 += std::bind(&stA::fun, &t, std::placeholders::_1, std::placeholders::_2);

  //广播
evnet1(, );

  //移除委托
evnet1 -= key1;
evnet1 -= key2;
evnet1(, );

  //清空事件
evnet1.Clear();
evnet1(, );//清空什么都不会输出
}

输出结果:

  在第一个版本的基础上增加了+=和-=运算符,使用法更接近c#,这里+=会返回一个key,这个key用来-=删除委托时用到,这种做法不太好,只是一个简单的处理。如果内部用vector的话,-=时,根据function去删除指定的委托的话,用法就和c#完全一致了,不过,这里遇到的问题是function不支持比较操作,导致将function存入容器后,后面再根据function去删除时就找不到对应的function了。还没有足够的时间去研究这个问题,留到后面再想办法解决function比较的问题。

如果读者有更好的解决办法不妨提出来,讨论一下。

c++11 boost技术交流群:296561497,欢迎大家来交流技术。

最新文章

  1. Lock+Condition 相对于 wait+notify 的一个优势案例分析
  2. 抄书 Copying Books UVa 714
  3. Annotation
  4. [ASP.NET] 下一代ASP.NET开发规范:OWIN
  5. Spark服务启动的一些总结
  6. Redis和Memcache对比及选择
  7. Android_menu_optionMenu
  8. 使用pdb调试python
  9. hdu 5115 Dire Wolf(区间dp)
  10. Ubuntu小私房(3)--Uubutnu启动美化大变身
  11. mac 电脑配置cordova
  12. 【DDD】业务建模实践 —— 人关注人
  13. SpringMvc+JavaConfig+Idea 搭建项目
  14. pycharm移动项目文件后,运行报错
  15. 简易远程消息交换协议SRMP
  16. Fiddler使用
  17. echars关系图
  18. Webservice之axis
  19. Java 对象 引用,equal == string
  20. 探索C#字符串

热门文章

  1. Spring Cloud环境搭建: Eureka Server
  2. 转:OGRE 渲染通路(Pass)
  3. UINavigationController出现nested push animation can result in corrupted navigation bar的错误提示
  4. js判断当前移到浏览器版本
  5. CentOS 7 使用 Yum 软件源安装谷歌 Chrome 浏览器
  6. iOS之ProtocolBuffer搭建
  7. HDU 4324 Triangle LOVE (拓扑排序)
  8. jQuery.ajax发送image请求格式
  9. CocoaPods iOS 开源库管理
  10. IDEA使用笔记(五)——*.properties中文乱码的修正