IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 观察者机制————利用回调函数实现 -> 正文阅读

[C++知识库]观察者机制————利用回调函数实现

作者:token comment

一、介绍:

此工具实现了观察者机制(同进程内交互)。

此工具的优势:
1、客户不需要针对客户特性实现观察者、通知者类,是一个即拿即用的工具;
2、观察者与通知者相互解耦。

当前缺陷:
1、未加锁,不保证线程安全;
2、消息内容固定为int,未扩展:制约了回调函数与通知函数;
3、未考虑性能问题,只是玩具级工具;
4、未实现解观察detach()与释放主题release()两函数;

注:
1、以上缺陷只是待补充部分代码,不影响整个观察者机制的设计思想,待空了再修正。
2、本框架用到了之前编写的单例模式框架代码、宏声明构造函数等,全部代码见github仓

二、观察者机制框架类:

2.1、框架代码:

头文件:notifier_and_observer.h

// notifier_and_observer.h
// description: 观察者机制
// author: XXX
// date: XXX

#ifndef INCLUDE_TOOLS_NOTIFIER_AND_OBSERVER
#define INCLUDE_TOOLS_NOTIFIER_AND_OBSERVER

#include <iostream>
#include <atomic>
#include <utility>
#include <functional>
#include <vector>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include "class_register.h"

using subject_t = uint16_t;

// 主题用于发布主题对应信息
class subject_content
{
public:
    subject_content(subject_t subject) : subject_(subject) {}

    void notify(std::vector<int> content);

private:
    subject_t subject_;
};

// 通知者用于建立主题
class notifier
{
public:
    notifier() = default;

    DISALLOW_COPY_AND_ASSIGN(notifier);

    void build_subject(subject_t subject);

    std::shared_ptr<subject_content> query_subject(subject_t subject);
};

// 暂定回调函数入参为主题类型与值为int组成的vector,之后可扩展
using observer_cb_t = std::function<void(subject_t, std::vector<int>)>;

// 观察者用于观察主题
class observer
{
public:
    observer() = default;

    void attach(subject_t subject, observer_cb_t observer_cb);

    DISALLOW_COPY_AND_ASSIGN(observer);
};

// 中介者:用于通知者与观察者解耦,对客户不可见,保存两者数据。
class observer_container
{
public:
    using subject_cb_container_t = std::unordered_map<subject_t, std::vector<observer_cb_t>>;

    using subject_container_t = std::unordered_map<subject_t, std::shared_ptr<subject_content>>;

public:
    SINGLETON_CLASS(observer_container);

    void attach(subject_t subject, observer_cb_t observer_cb);

    void build_subject(subject_t subject);

    std::shared_ptr<subject_content> query_subject(subject_t subject);

    std::vector<observer_cb_t> query_observer(subject_t subject);

private:
    observer_container() = default;

private:
    subject_cb_container_t subject_cb_container;

    subject_container_t subject_container;
};

#endif

源文件:notifier_and_observer.cpp

// description: 观察者机制
// author: XXX
// date: XXX

#include "../../include/tools/notifier_and_observer.h"
#include <iostream>
#include <atomic>
#include <utility>
#include <functional>
#include <vector>

void subject_content::notify(std::vector<int> content)
{
    auto observer_cbs = observer_container::get_instance()->query_observer(subject_);
    for (auto &each : observer_cbs) {
        each(subject_, content);
    }
}

void observer::attach(subject_t subject, observer_cb_t observer_cb)
{
    observer_container::get_instance()->attach(subject, observer_cb);
}

void notifier::build_subject(subject_t subject)
{
    observer_container::get_instance()->build_subject(subject);
}

std::shared_ptr<subject_content>  notifier::query_subject(subject_t subject)
{
    return observer_container::get_instance()->query_subject(subject);
}

void observer_container::attach(subject_t subject, observer_cb_t observer_cb)
{
    // 主题未注册则观察失败
    if (subject_container.find(subject) == subject_container.end()) {
        std::cout << "subject: " << subject << " is not build" << std::endl;
        return;
    }

    // 主题注册后,再添加该主题的观察者
    auto subjectcb_iter = subject_cb_container.find(subject);
    if (subjectcb_iter == subject_cb_container.end()) {
        subject_cb_container[subject] = {observer_cb};
    } else {
        subjectcb_iter->second.push_back(observer_cb);
    }
    std::cout << "attach subject: " << subject << std::endl;

}

void observer_container::build_subject(subject_t subject)
{
    if (subject_container.find(subject) == subject_container.end()) {
        subject_container[subject] = std::make_shared<subject_content>(subject);
        std::cout << "build_subject: " << subject << std::endl;
        return;
    }
    std::cout << "subject: " << subject << "already build" << std::endl;
}

std::shared_ptr<subject_content> observer_container::query_subject(subject_t subject)
{
    auto subject_content_iter = subject_container.find(subject);
    if (subject_content_iter == subject_container.end()) {
        return nullptr;
    }
    return subject_content_iter->second;
}

std::vector<observer_cb_t> observer_container::query_observer(subject_t subject)
{
    auto subject_cb_iter = subject_cb_container.find(subject);
    return (subject_cb_iter == subject_cb_container.end()) ? std::vector<observer_cb_t>() : subject_cb_iter->second;
}

2.2、客户侧代码:

void cb1(subject_t subject, std::vector<int> message)
{
    std::cout << "cb1 receive notified message, subject  is: " << subject << " message is ";
    for (auto each : message) {
        std::cout << each << " ";
    }
    std::cout << std::endl;
}

void cb2(subject_t subject, std::vector<int> message)
{
    std::cout << "cb2 receive notified message, subject  is: " << subject << std::endl;
}

void test_notifier_and_observer()
{
    // 1、建立主题
    subject_t  theme =  1;
    notifier().build_subject(theme);
    // 2、观察主题
    observer().attach(theme, cb1);
    observer().attach(theme, cb2);

    // 3、通知主题
    {
        // 3.1、通知者定义通知的内容(之后可以用数据流,提升通知内容的扩展性)
        std::vector<int> message{1,2,3};

        // 3.2、通知者先查询主题是否存在:
        auto subject = notifier().query_subject(theme);
        if (subject ==  nullptr) {
            std::cout << "subject: " << theme << " not exist" << std::endl;
        }

        // 3.3、主题发布通知(之后可以将当前有无观察者信息体现在客户侧)
        subject->notify(message);
    }
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-06 10:54:21  更:2022-05-06 10:55:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 2:10:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码