`

C++11应用:观察者模式(多函数对象回调)

 
阅读更多

    CallbackNotify.hpp

#pragma once

#include <map>

template <typename Func>
class CallbackNotify
{
private:
	CallbackNotify(const CallbackNotify&) = delete; // 禁用复制函数
	CallbackNotify& operator= (const CallbackNotify&) = delete; // 禁用赋值构造

	int m_observerId = 0; // 观察者对应的编号
	std::map<int, Func> m_connections; // 观察者列表

									   // 保存观察者并分配观察者编号
	template <typename F>
	int Assign(F&& f)
	{
		int k = m_observerId++;
		m_connections.emplace(k, std::forward<F>(f));
		return k;
	}
public:
	CallbackNotify() = default;// 使用C++11提供的默认构造函数
	virtual ~CallbackNotify() {
		m_connections.clear();
		m_observerId = 0;
	}
	// 注册观察者,支持右值引用
	int Connect(Func&& f)
	{
		return Assign(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)...); // 函数对象执行参数
		}
	}
};

    测试:

#include <iostream>
#include <string>  

#include <functional>

#include "CallbackNotify.hpp"

using namespace std;
   
struct TestA
{
	int a;
	int b;
	void print(int x, int y)
	{
		cout << "TestA print:" << x << "," << y << endl;
	}
	void printNoParam() {
		cout << "TestA printNoParam:" << a << "," << b << endl;
	}
};

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

void test() {
	CallbackNotify<std::function<void(int, int)>> myevent; // 申明注册的函数对象是两个参数的int
	auto key1 = myevent.Connect(std::move(printLocal)); // 以函数方式注册观察者

	TestA testA;
	auto key2 = myevent.Connect([&testA](int a, int b) {testA.a = a; testA.b = b; }); // lambda注册

	auto key3 = myevent.Connect([](int a, int b) {cout << "lambda print:" << a << "," << b << endl; }); // lambda注册

																										// std::function注册
	std::function<void(int, int)> f1 = std::bind(&TestA::print, &testA, std::placeholders::_1, std::placeholders::_2);
	auto key4 = myevent.Connect(std::move(f1));

	std::function<void(int, int)> f2 = printLocal;
	auto key5 = myevent.Connect(std::move(f2));

	int a = 1;
	int b = 2;
	myevent.Notify(a, b); // 触发

	testA.printNoParam();

	myevent.Disconnect(key1); //移除
	 
}
int main(int, char *[])
{     
	test();

	system("pause");
	return 0;
}

  

分享到:
评论

相关推荐

    超级有影响力霸气的Java面试题大全文档

    多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 5、String是最基本的数据类型吗?  基本数据类型包括byte、int、char、long、float、double、boolean和short。  java....

    传智播客扫地僧视频讲义源码

    本教程共分为5个部分,第一部分是C语言提高部分,第二部分为C++基础部分,第三部分为C++进阶部分,第四部分为C、C++及数据结构基础部分,第五部分为C_C++与设计模式基础,内容非常详细. 第一部分 C语言提高部分目录...

    SimpleObserver.rar

    基于可变参回调的观察者/发布订阅模式,回调函数参数为可变参,使用简单,封装简洁,有使用示例

    asp.net知识库

    Asp.Net2.0无刷新客户端回调 体验.net 2.0 的优雅(1) -- 异步WebService调用 ASP.NET 2.0页面框架的几点新功能 ASP.NET 2.0 中收集的小功能点 asp.net2.0中的webpart使用小记 2.0问题、错误解决办法 ASP.NET 2.0...

    windows驱动开发技术详解-part2

     1.4.7 HelloWDM对其他IRP的回调函数  1.4.8 HelloWDM的卸载例程  1.5 HelloWDM的编译和安装  1.5.1 用DDK编译环境编译HelloWDM  1.5.2 HelloWDM的编译过程  1.5.3 安装HelloWDM  1.6 小结  第2章 ...

    Windows驱动开发技术详解的光盘-part1

     1.4.7 HelloWDM对其他IRP的回调函数  1.4.8 HelloWDM的卸载例程  1.5 HelloWDM的编译和安装  1.5.1 用DDK编译环境编译HelloWDM  1.5.2 HelloWDM的编译过程  1.5.3 安装HelloWDM  1.6 小结  第2章 ...

    libsig:CC++ 的 SignalEvent 处理库

    ligsig 是 C 和 C++ 的信号/事件库,它允许像观察者模式一样处理信号/事件。 成员函数也可以用作回调。 每个信号都有一个信号上下文,允许信号在它们自己的上下文中使用。 此外,可以在系统上下文 (sig_sys_ctx) ...

    java 面试题 总结

    多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 2、String是最基本的数据类型吗? 基本数据类型包括byte、int、char、long、float、double、boolean和short。 java.lang....

    Thinking in Java 中文第四版+习题答案

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    Java初学者入门教学

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    Think in Java(中文版)chm格式

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ...

    JAVA_Thinking in Java

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    ThinkInJava

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    java 编程入门思考

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    thinkinjava

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

    Thinking in Java简体中文(全)

    A.3.4 编写回调函数 A.3.5 其他J/Direct特性 A.4 本原接口(RNI) A.4.1 RNI总结 A.5 Java/COM集成 A.5.1 COM基础 A.5.2 MS Java/COM集成 A.5.3 用Java设计COM服务器 A.5.4 用Java设计COM客户 A.5.5 ActiveX/Beans...

Global site tag (gtag.js) - Google Analytics