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

2024-06-16 06:52

本文主要是介绍观察者模式(大话设计模式)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;
}

这篇关于观察者模式(大话设计模式)C/C++版本的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1065745

相关文章

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

C++打印 vector的几种方法小结

《C++打印vector的几种方法小结》本文介绍了C++中遍历vector的几种方法,包括使用迭代器、auto关键字、typedef、计数器以及C++11引入的范围基础循环,具有一定的参考价值,感兴... 目录1. 使用迭代器2. 使用 auto (C++11) / typedef / type alias

Go语言实现桥接模式

《Go语言实现桥接模式》桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化,本文就来介绍一下了Go语言实现桥接模式,感兴趣的可以了解一下... 目录简介核心概念为什么使用桥接模式?应用场景案例分析步骤一:定义实现接口步骤二:创建具体实现类步骤三:定义抽象类步骤四:创建扩展抽象类步

C++ scoped_ptr 和 unique_ptr对比分析

《C++scoped_ptr和unique_ptr对比分析》本文介绍了C++中的`scoped_ptr`和`unique_ptr`,详细比较了它们的特性、使用场景以及现代C++推荐的使用`uni... 目录1. scoped_ptr基本特性主要特点2. unique_ptr基本用法3. 主要区别对比4. u

C++11中的包装器实战案例

《C++11中的包装器实战案例》本文给大家介绍C++11中的包装器实战案例,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录引言1.std::function1.1.什么是std::function1.2.核心用法1.2.1.包装普通函数1.2.

C++多线程开发环境配置方法

《C++多线程开发环境配置方法》文章详细介绍了如何在Windows上安装MinGW-w64和VSCode,并配置环境变量和编译任务,使用VSCode创建一个C++多线程测试项目,并通过配置tasks.... 目录下载安装 MinGW-w64下载安装VS code创建测试项目配置编译任务创建 tasks.js

C++ 多态性实战之何时使用 virtual 和 override的问题解析

《C++多态性实战之何时使用virtual和override的问题解析》在面向对象编程中,多态是一个核心概念,很多开发者在遇到override编译错误时,不清楚是否需要将基类函数声明为virt... 目录C++ 多态性实战:何时使用 virtual 和 override?引言问题场景判断是否需要多态的三个关