观察者模式(大话设计模式)C/C++版本

观察者模式

在这里插入图片描述

扩展:观察者模式——委托

C++

参考:https://www.cnblogs.com/Galesaur-wcy/p/15905936.html

#include <iostream>
#include <list>
#include <memory>
#include <string>
using namespace std;

// Observer类 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口要做更新接口。
// 观察者一般用一个抽象类或者接口实现,更新接口通常包含一个Update()方法 这个方法叫做更新方法。
class Observer
{
public:
    virtual void Update(int) = 0;
    virtual ~Observer() = default;
    virtual void SetName(const string &observerName) final
    {
        m_observerName = observerName;
    }
    virtual string GetName() const final
    {
        return m_observerName;
    }

protected:
    string m_observerName;
};

// Subject类 可翻译为主题或抽象通知者 一般用一个抽象类或者一个接口实现。他把所有对观察者对象的引用保存
// 在一个聚集里,每个主题都可以又任何数量的观察者。抽象主题提供一个接口,可增加或者删除观察者对象
class Subject
{
public:
    virtual void Attach(shared_ptr<Observer>) = 0;
    virtual void Detach(shared_ptr<Observer>) = 0;
    virtual void Notify() = 0;
};

// ConcreteObserver 具体观察者 实现抽象观察角色所要求的更新接口,以便使本身的状态与主题的状态相协调.
// 具体观察者角色可以保存一个指向具体主题对象的引用.具体观察者校色通常用一个具体子类实现
class ConcreteObserver : public Observer
{
public:
    ConcreteObserver(shared_ptr<Subject> pSubject, const string &observerName)
        : m_pSubject(pSubject)
    {
        m_observerName = observerName;
    }
    void Update(int value) override
    {
        cout << "   ConcreteObserver " << m_observerName << " gets the update. New State: " << value << endl;
    }

private:
    shared_ptr<Subject> m_pSubject;
};

class ConcreteObserver2 : public Observer
{
public:
    ConcreteObserver2(shared_ptr<Subject> pSubject, const string &observerName)
        : m_pSubject(pSubject)
    {
        m_observerName = observerName;
    }
    void Update(int value) override
    {
        cout << "   ConcreteObserver2 " << m_observerName << " gets the update. New State: " << value << endl;
    }

private:
    shared_ptr<Subject> m_pSubject;
};

// ConcreteSubject类,叫做具体主题或者具体通知者..将有关状态存入具体观察者对象;在具体主题内部状态改变时...给所有登记过的观察者发出通知.
// 具体主题对象通常用一个具体子类实现.
class ConcreteSubject : public Subject
{
public:
    void Attach(shared_ptr<Observer> pObserver)
    {
        m_ObserverList.push_back(pObserver);
    }
    void Detach(shared_ptr<Observer> pObserver)
    {
        m_ObserverList.remove_if([=](const shared_ptr<Observer> &observer)
                                 { return observer == pObserver; });
    }
    void Notify()
    {
        for (const auto &observer : m_ObserverList)
        {
            cout << "   Notifying -> " << observer->GetName() << endl;
            observer->Update(m_iState);
        }
    }

    void SetState(int state)
    {
        cout << "State changed to " << state << endl;
        m_iState = state;
    }

private:
    list<shared_ptr<Observer>> m_ObserverList;
    int m_iState;
};

int main()
{
    auto pSubject = make_shared<ConcreteSubject>();

    auto pObserver = make_shared<ConcreteObserver>(pSubject, "observer1");
    auto pObserver2 = make_shared<ConcreteObserver2>(pSubject, "observer2");

    pSubject->Attach(pObserver);
    pSubject->Attach(pObserver2);

    pSubject->SetState(2);
    pSubject->Notify();
    cout << endl;

    pSubject->Detach(pObserver);

    pSubject->SetState(3);
    pSubject->Notify();
    cout << endl;

    return 0;
}

C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef struct Subject Subject;
typedef struct Observer
{
    char *name;
    void (*update)(struct Subject *, int, void *);
} Observer;

typedef struct Subject
{
    struct Observer **observers;
    size_t observer_count;
    int state;
} Subject;

void ConcreteObserverUpdate(struct Subject *subject, int value, void *data)
{
    printf("   ConcreteObserver get the update. New State: %d\n", value);
}

void ConcreteObserver2Update(struct Subject *subject, int value, void *data)
{
    printf("   ConcreteObserver2 get the update. New State: %d\n", value);
}

void attach(struct Subject *subject, Observer *observer)
{
    Observer **newObservers = realloc(subject->observers, sizeof(Observer *) * (subject->observer_count + 1));
    if (newObservers == NULL)
    {
        fprintf(stderr, "Memory allocation failed.\n");
        exit(EXIT_FAILURE);
    }
    newObservers[subject->observer_count++] = observer;
    subject->observers = newObservers;
}

void detach(struct Subject *subject, Observer *observer)
{
    bool removed = false;
    int i;
    for (i = 0; i < subject->observer_count; ++i)
    {
        if (subject->observers[i] == observer)
        {
            subject->observer_count--;
            removed = true;
            int j;
            for (j = i; j < subject->observer_count; ++j)
            {
                subject->observers[j] = subject->observers[j + 1];
            }
            break;
        }
    }
    if (!removed)
    {
        fprintf(stderr, "Observer not found.\n");
    }
}

void notify(struct Subject *subject)
{
    int i;
    for (i = 0; i < subject->observer_count; ++i)
    {
        printf("   Notifying -> %s\n", subject->observers[i]->name);
        subject->observers[i]->update(subject, subject->state, subject->observers[i]);
    }
}

void setState(struct Subject *subject, int state)
{
    printf("state changed......\n");
    subject->state = state;
}

void safe_free(void *ptr)
{
    if (ptr)
        free(ptr);
}

int main()
{
    Subject *pSubject = (Subject *)malloc(sizeof(Subject));
    pSubject->observers = NULL;
    pSubject->observer_count = 0;
    pSubject->state = 0;

    Observer observer1 = {
        .name = strdup("observer1"),
        observer1.update = ConcreteObserverUpdate,
    };

    Observer observer2 = {
        .name = strdup("observer2"),
        .update = ConcreteObserver2Update,
    };

    attach(pSubject, &observer1);
    attach(pSubject, &observer2);

    setState(pSubject, 2);
    notify(pSubject);
    printf("\n");

    detach(pSubject, &observer1);

    setState(pSubject, 3);
    notify(pSubject);
    printf("\n");

    safe_free(observer1.name);
    safe_free(observer2.name);
    safe_free(pSubject->observers);
    safe_free(pSubject);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/711385.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spine学习09】之导入皮肤两种方式[skin]

第一种&#xff1a;明确项目中某个角色是有两套皮肤的情况下 直接导入两套皮肤 1、添加SKIN皮肤指令 2、在ps中-文件-脚本-浏览【打开选中jsx脚本】 3、打开Spine 点击左上角&#xff0c;选择导入数据 就可以看到该角色的两套皮肤啦&#xff01; 第二种&#xff1a;刚开始角…

探索档案未来,尽在ARCHE-2024

2024年第三届上海国际智慧档案展览会暨高峰论坛&#xff08;ARCHE-2024&#xff09;将于2024年6月19日至21日在上海跨国采购会展中心隆重举行。深圳市铨顺宏科技有限公司应邀参展&#xff0c;将以全新形象盛装亮相&#xff0c;展示其在档案管理领域的最新技术和解决方案。 ARC…

2024年【N2观光车和观光列车司机】考试技巧及N2观光车和观光列车司机模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 N2观光车和观光列车司机考试技巧参考答案及N2观光车和观光列车司机考试试题解析是安全生产模拟考试一点通题库老师及N2观光车和观光列车司机操作证已考过的学员汇总&#xff0c;相对有效帮助N2观光车和观光列车司机模…

网络安全形势迫在眉睫!云WAF保护私有云安全!

业务上云面临新的WEB安全挑战 目前&#xff0c;所有的组织都在积极地接受企业的“云”&#xff0c;推进数字化变革。在服务云计算和私有云平台构建中&#xff0c;用户除了要面对各种常见的网络攻击&#xff0c;还需要面对虚拟环境下的非授权访问、虚拟机逃逸和敏感信息泄漏等问…

【Mongodb-01】Mongodb亿级数据性能测试和压测

mongodb数据性能测试 一&#xff0c;mongodb数据性能测试1&#xff0c;mongodb数据库创建和索引设置2&#xff0c;线程池批量方式插入数据3&#xff0c;一千万数据性能测试4&#xff0c;两千万数据性能测试5&#xff0c;五千万数据性能测试6&#xff0c;一亿条数据性能测试7&am…

Java新特性与性能调优

引言 Java不断演进&#xff0c;每个新版本都引入了新的特性和改进&#xff0c;帮助开发者在提高生产力的同时&#xff0c;也能更好地优化程序性能。本文将详细介绍Java新版本中的重要特性&#xff0c;如从Java 8到Java 17&#xff0c;并探讨性能调优的方法&#xff0c;包括JVM调…

Python自动化办公(二) —— 查看文件夹中的PDF文件数量

Python自动化办公&#xff08;二&#xff09; —— 查看文件夹中的PDF文件数量 在日常办公中&#xff0c;我们经常需要统计某个文件夹中的PDF文件数量。手动操作不仅费时费力&#xff0c;而且容易出错。幸运的是&#xff0c;使用Python可以轻松实现这个过程。本文将介绍如何使用…

【字符串函数2】

5. strncpy 函数的使用和模拟实现 选择性拷贝 char * strncpy ( char * destination, const char * source, size_t num ); 1.拷贝num个字符从源字符串到目标空间。 2.如果源字符串的⻓度⼩于num&#xff0c;则拷⻉完源字符串之后&#xff0c;在⽬标的后边 追加0 &#…

MyBatis-Plus整合达梦数据库

文章目录 1. 环境准备2. 创建Spring Boot项目3. 引入依赖4. 配置数据源5. 配置MyBatis-Plus6. 创建实体类7. 创建Mapper接口8. 创建Service类9. 创建Controller类10. 创建Mapper XML文件11. 测试12. 进一步优化12.1 配置分页插件12.2 配置乐观锁插件13. 总结🎉欢迎来到Java学…

案例学习-存量更新规划实施探索(武汉)

案例学习-存量更新规划实施探索&#xff08;武汉&#xff09; 武汉市在早期旧城更新实践中发现零散化的更新往往导致资源配置分散、城市建设破碎化等弊病&#xff0c;特别是由于过于强调项目自身“经济平衡”&#xff0c;在实施过程中也逐步暴露出住宅占比过大、强度偏高、公服…

屹晶微EG3002 单通道功率MOSFET驱动芯片 贴片SOP8

EG3002作为一款功率MOSFET驱动芯片&#xff0c;它的应用领域主要取决于其技术参数和性能特点。根据之前提供的信息&#xff0c;EG3002可能适用于以下领域&#xff1a; 1. 电源管理&#xff1a;用于高效率电源转换器&#xff0c;如开关电源&#xff08;SMPS&#xff09;、电池充…

yolov8通过训练完成的模型生成图片热力图--论文需要

源代码来自于网络 使用pytorch_grad_cam&#xff0c;对特定图片生成热力图结果。 安装热力图工具 pip install pytorch_grad_cam pip install grad-cam# get_params中的参数&#xff1a; # weight&#xff1a; # 模型权重文件&#xff0c;代码默认是yolov8m.pt # c…

希亦、添可、石头洗地机哪款好用?2024洗地机深度测评

今年的洗地机市场竞争异常激烈&#xff0c;各大品牌纷纷推出了自己的旗舰产品。这对消费者来说是个好消息&#xff0c;因为有更多的选择空间。然而&#xff0c;面对如此多的优质洗地机&#xff0c;选择合适的一款也成了一种“幸福的烦恼”。 作为一个专业的测评人士&#xff0…

【笔记】【矩阵的二分】668. 乘法表中第k小的数

力扣链接&#xff1a;题目 参考地址&#xff1a;参考 思路&#xff1a;二分查找 把矩阵想象成一维的已排好序的数组&#xff0c;用二分法找第k小的数字。 假设m行n列&#xff0c;则对应一维下标范围是从1到mn&#xff0c;初始&#xff1a; l1; rmn; mid(lr)/2 设mid在第i行&a…

【源码】综合股票币币合约交易所源码/etf交易所源码/美股港股台股交易所源码

支持多国语言 全开源可二开的一个版本&#xff01;支持虚拟货币 ETF 外汇 美股 A股 港股 台股。 前端是VUE开发&#xff08;带vue工程源码&#xff09;后端JAVA开发&#xff01;搭建也相对简单。 总的来说功能非常强大&#xff0c;适合线上运营的一个版本&#xff0c;有兴趣的可…

Linux--08---挂载分区

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.查看系统磁盘分区情况1.lsblk 查看2.fdisk -l 2.挂载未分区磁盘1. 创建分区2. 格式化分区3. 创建挂载点4. 挂载分区5. 更新 /etc/fstab6.验证挂载 3.修改挂载的磁…

样本学习:当AI遇上“少见多怪”

东汉名臣牟融在其著作《牟子》写道&#xff1a;“少所见&#xff0c;多所怪&#xff0c;睹橐驼&#xff0c;谓马肿背。”意思是见闻少的人遇到不常见的事物就觉得奇怪&#xff0c;见到骆驼也以为是背肿了的马。因此&#xff0c;后人总用“少见多怪”来嘲笑见识浅陋的人。然而&a…

springboot依赖管理和自动配置

依赖管理和自动配置 依赖管理和自动配置依赖管理什么是依赖管理修改自动仲裁/默认版本号 starter场景启动器starter场景启动器基本介绍官方提供的starter第三方starter 自动配置自动配置基本介绍SpringBoot自动配置了哪些?如何修改默认配置如何修改默认扫描包结构resources\ap…

profile-3d-contrib,github三维立体图的使用

图片展示: 提示: 这个profile-3d-contrib存储库有时候会出现问题,导致又有使用这个存储库svg的用户显示出现问题. 参考: https://zhuanlan.zhihu.com/p/681786778 原仓库链接&#xff1a; GitHub - yoshi389111/github-profile-3d-contrib: This GitHub Action creates a Gi…

南通国际高中有哪些?南通惠立学校高中部校长见面日重磅来袭

惠灵顿&#xff08;中国&#xff09;自2011年成立以来&#xff0c;一直坚持深耕国际与双语教育&#xff0c;拥有丰厚的办学经验。依托于集团化的深厚经验南通惠立学校于2024-2025学年开设9-11年级&#xff0c;这所南通国际高中为高中学生搭建一个集卓越升学成果、强大师资、纯正…