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

news2024/7/6 19:31:12

观察者模式

在这里插入图片描述

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

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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

港科夜闻 | 香港科大与香港科大(广州)合推红鸟跨校园学习计划,共享教学资源,促进港穗学生交流学习...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与香港科大(广州)合推“红鸟跨校园学习计划”&#xff0c;共享教学资源&#xff0c;促进港穗学生交流学习。香港科大与香港科大(广州)6月14日共同宣布推出“红鸟跨校园学习计划”&#xff0c;以进一步加强两校学…

5.拼数 - 蓝桥杯

基础知识要求&#xff1a; Java&#xff1a;for循环、if判断、Scanner类、数组、字符串 Python&#xff1a; for循环、if判断、列表、字符串、input() 题目&#xff1a; 思路解析&#xff1a; 读取输入&#xff1a; 首先读取要排序的字符串数量。然后读取相应数量的字符串&am…

【Redis】String的常用命令及图解String使用场景

本文将详细介绍 Redis String 类型的常见命令及其使用场景&#xff0c;包括缓存、计数器、共享会话、手机验证码、分布式锁等场景&#xff0c;并且配图和伪代码进一步方便理解和使用。 命令执行效果时间复杂度set key value [key value…]设置key的值是valueO(k),k是键个数get…

使用消息队列(MQ)实现MySQL持久化存储与MySQL server has gone away问题解决

在现代应用程序开发中&#xff0c;消息队列&#xff08;MQ&#xff09;扮演着重要的角色。它们可以帮助我们解决异步通信和解耦系统组件之间的依赖关系。而其中一个常见的需求是将消息队列中的数据持久化到数据库中&#xff0c;以确保数据的安全性和可靠性。在本文中&#xff0…

gbase8s数据库阻塞检查点和非阻塞检查点的执行机制

1. 检查点的描述 为了便于数据库系统的复原和逻辑恢复&#xff0c;数据库服务器生成的一致性标志点&#xff0c;称为检查点&#xff0c;其是建立在数据库系统的已知和一致状态时日志中的某个时间点检查点的目的在于定期将逻辑日志中的重新启动点向前移动 如果存在检查点&#…

【Quartus 13.0】NIOS II 部署UART 和 PWM

打算在 EP1C3T144I7 芯片上部署 nios ii 做 uart & pwm控制 这个芯片或许不够做 QT 部署 这个芯片好老啊&#xff0c;但是做控制足够了&#xff0c;我只是想装13写 leader给的接口代码是用VHDL写的&#xff0c;我不会 当然verilog我也不太会 就这样&#xff0c;随便写吧 co…

[大模型]XVERSE-7B-chat Transformers 推理

XVERSE-7B-Chat为XVERSE-7B模型对齐后的版本。 XVERSE-7B 是由深圳元象科技自主研发的支持多语言的大语言模型&#xff08;Large Language Model&#xff09;&#xff0c;参数规模为 70 亿&#xff0c;主要特点如下&#xff1a; 模型结构&#xff1a;XVERSE-7B 使用主流 Deco…

【ARMv8/ARMv9 硬件加速系列 3.2 -- SVE 读写内存指令 st1b | st1w | st1w | st1d 使用介绍】

文章目录 SVE Load 和 Store 指令使用介绍LD1 加载指令ST1 存储指令PFR 预取指令参考示例LD1 加载示例ST1 存储示例 代码实例 SVE Load 和 Store 指令使用介绍 ARMv9架构中的SVE&#xff08;Scalable Vector Extension&#xff09;指令集为向量计算提供了强大支持&#xff0c;…

fs.1.10 ON rockeylinux8 dockerfile模式

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 rockeylinux8 docker上编译安装fs.1.10的流程记录&#xff0c;本文使用dockerfile模式。 环境 docker engine&#xff1a;Version 24.0.6 rockylinux docker&#xff1a;8 freeswitch&#xff1a;v1.10.7 dockerfi…

CleanMyMacX4.15.4如何优化苹果电脑系统缓存,告别MacBook卡顿,提升mac电脑性能

你是否曾为苹果电脑存储空间不够而烦恼&#xff1f;是否曾因系统运行缓慢而苦恼&#xff1f;别担心&#xff0c;今天我要给大家种草一个神器——CleanMyMac&#xff01;这款软件可以帮助你轻松解决苹果电脑的种种问题&#xff0c;让你的电脑焕然一新&#xff01; 让我来给大家介…

显著提高iOS应用中Web页面的加载速度 - 提前下载页面的关键资源(如JavaScript、CSS和图像)

手动下载并缓存资源是一种有效的方式&#xff0c;可以确保在需要时资源已经在本地存储&#xff0c;这样可以显著提高加载速度。 缓存整个 web 页面的所有资源文件 具体实现步骤 下载和缓存资源&#xff1a;包括 HTML 文件、CSS、JavaScript 和图像。在应用启动时预加载资源。…

CSS从入门到精通——动画:CSS3动画执行次数和逆向播放

目录 任务描述 相关知识 动画执行次数 动画反向播放 编程要求 任务描述 本关任务&#xff1a;用 CSS3 实现loading效果。效果图如下&#xff1a; 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.动画执行次数&#xff0c;2.动画反向播放。 需要实现的效…

CSS从入门到精通——动画:CSS3动画延迟和完成后状态的保持

目录 任务描述 相关知识 动画状态 动画完成时的状态 动画延迟 编程要求 任务描述 本关任务&#xff1a;用 CSS3 实现小车等待红绿灯的效果。效果图如下&#xff1a; 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.动画状态&#xff0c;2.动画完成时的状…

mac下Xcode在iphone真机上测试运行iOS软件

最近一个需求需要在iPhone真机上测试一个视频直播的项目。 需要解决如何将项目 app 安装到真机上 在进行真机调试。 安装Xcode 直接在App Store上搜索Xcode安装即可。 关键是要安装Simulator。项目需要安装iOS17.5但是由于安装包太大&#xff0c;并且网络不稳定的原因。在Xco…

关于yolov5训练的那些事儿

1.YOLOv5 的模型系列包括从最小到最大的多种模型&#xff1a;YOLOv5n&#xff08;Nano&#xff09;&#xff0c;YOLOv5s&#xff08;Small&#xff09;&#xff0c;YOLOv5m&#xff08;Medium&#xff09;&#xff0c;YOLOv5l&#xff08;Large&#xff09;&#xff0c;以及 YO…

【Linux硬盘读取】Windows下读取Linux系统的文件解决方案:Linux Reader4.5 By DiskInternals

前言 相信做机器视觉相关的很多人都会安装 Windows 和 Linux 双系统。在 Linux 下&#xff0c;我们可以很方便的访问Windows的磁盘&#xff0c;反过来却不行。但是这又是必须的。通过亲身体验&#xff0c;向大家推荐这么一个工具&#xff0c;可以让 Windows 方便的访问 Ext 2/3…

Linux 文件的权限信息解读 chmod修改权限 数字序号表示权限

ls -l #列出当前文件 显示详细信息 drwxr-xr-x. 2 dpc test 6 Jun 15 07:45 test.txt共分为三部分 drwxr-xr-x.&#xff1a;表示文件和文件夹的权限信息dpc &#xff1a;文件&#xff0c;文件夹所属的用户test &#xff1a; 文件和文件夹所属的用户组 drwxr-xr-x 解读 d表示为…

实用软件下载:BetterZip 5最新安装包及详细安装教程

BetterZip是一款功能强大的Mac解/压缩软件&#xff0c;可以满足用户对文件压缩、解压、加密和保护等方面的需求。以下是关于BetterZip软件的主要功能、特点和使用方法的详细介绍&#xff0c;以及对其用户友好度、稳定性和安全性的评价。 安 装 包 获 取 地 址: BetterZip 5-安…

【尚庭公寓SpringBoot + Vue 项目实战】公寓管理(十一)

【尚庭公寓SpringBoot Vue 项目实战】公寓管理&#xff08;十一&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】公寓管理&#xff08;十一&#xff09;1、业务介绍2、逻辑模型介绍3、接口开发3.1、保存或更新公寓信息3.2、根据条件分页查询详细信息3.3、根据ID获…

深度学习(七)——神经网络的卷积操作

卷积操作 一、torch.nn中Convolution Layers函数的介绍 1. 参数介绍 nn.Conv1d: Conv取自Convolution的前四个字母&#xff0c;1d代表的是一个一维操作。 nn.Conv2d: 2d表示是一个二维的操作&#xff0c;比如图像就是一个二维的。 其余参数不常用&#xff0c;见官网文档&am…