博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(原创)c++11改进我们的模式之改进观察者模式
阅读量:5923 次
发布时间:2019-06-19

本文共 3422 字,大约阅读时间需要 11 分钟。

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

template
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
void Notify(Args&&... args) { for (auto& it: m_connections) { it.second(std::forward
(args)...); } }private: int m_nextKey; std::map
m_connections;};

 

测试代码:

struct stA { int a, b; };void print(int a, int b) { cout << a << ", " << b << endl; }void TestObserver(){	Events
> 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 template
class Events : NonCopyable{public: Events() :m_nextKey(0) {} ~Events(){} int operator += (Func&& f) { return Connect(std::forward
(f)); } int operator += (Func& f) { return Connect(f); } template
void operator()(Args&&... args) { Notify(std::forward
(args)...); } Events& operator -= (int key) { Disconnect(key); return *this; } void Clear() { m_connections.clear(); }private: int Connect(Func&& f) { return Assgin(std::forward
(f)); } int Connect(Func& f) { return Assgin(f); } void Disconnect(int key) { m_connections.erase(key); } template
void Notify(Args&&... args) { for (auto& it : m_connections) { it.second(std::forward
(args)...); } } template
int Assgin(F&& f) { int index = m_nextKey++; Push(index, std::forward
(f)); return index; } template
void Push(int index, F&& f) { m_connections.emplace(index, std::move(f)); } template
void Push(int index, F& f) { m_connections.emplace(index, f); }private: int m_nextKey; std::map
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
; using Event1 = Events
; 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(2, 3);   //移除委托 evnet1 -= key1; evnet1 -= key2; evnet1(4, 5);   //清空事件 evnet1.Clear(); evnet1(1, 2);//清空什么都不会输出}

输出结果:

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

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

 

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

转载地址:http://yrnvx.baihongyu.com/

你可能感兴趣的文章
杭州互联网公司汇总
查看>>
数据结构复习笔记(3)
查看>>
基于事件驱动的DDD领域驱动设计框架分享(附源代码)
查看>>
7.5。Outlook smime x509证书
查看>>
51Nod 1289 大鱼吃小鱼(模拟,经典好题)
查看>>
【Android疑难杂症】GridView动态设置Item的宽高导致第一个Item不响应或显示不正常的问题...
查看>>
一个线程封装类
查看>>
贪心算法
查看>>
把JScript函数模拟为"异步执行"方式
查看>>
7.13. rename file
查看>>
(第二天)原型、继承
查看>>
activiti bpmnModel使用
查看>>
《剑指offer》青蛙跳台阶
查看>>
关于MYSQL DML(UPDATE DELETE)中的子查询问题和ERROR 1093 (HY000)错误
查看>>
MAHOUT_LOCAL is not set; adding HADOOP_CONF_DIR to classpath.
查看>>
MySQL备份恢复第一篇
查看>>
数据泵导出出现ORA-31617错误
查看>>
【故障处理】因AIX异步IO没有开启导致SQL*Plus不可用
查看>>
[20160325]bbed 中文字符显示的显示问题
查看>>
移动开发中Fiddler的那些事儿 (转)
查看>>