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

news/发布时间2024/7/21 5:15:05

观察者模式-委托

先看该常规的没有委托概念的代码,如下:

非委托

#include <iostream>
#include <string>
#include <list>
using namespace std;class Subject; // 前向声明// 抽象观察者
class Observer
{
protected:string name;Subject *sub;public:Observer(string name, Subject *sub){this->name = name;this->sub = sub;}virtual void update() = 0;
};// 抽象通知者
class Subject
{
protected:list<Observer *> observers;public:string event;virtual void attach(Observer *) = 0;virtual void detach(Observer *) = 0;virtual void notify() = 0;
};// 具体通知者,秘书
class Secretary : public Subject
{void attach(Observer *observer) override{observers.push_back(observer);}void detach(Observer *observer) override{list<Observer *>::iterator iter = observers.begin();while (iter != observers.end()){if ((*iter) == observer){observers.erase(iter);}++iter;}}void notify() override{list<Observer *>::iterator iter = observers.begin();while (iter != observers.end()){(*iter)->update();++iter;}}
};// 具体的观察者,看股票的
class StockObserver : public Observer
{
public:StockObserver(string name, Subject *sub) : Observer(name, sub){}void update() override{cout << name << " 收到消息:" << sub->event << endl;if (sub->event == "梁所长来了!"){cout << "我马上关闭股票,装做很认真工作的样子!" << endl;}}
};// 具体的观察者,看NBA的
class NBAObserver : public Observer
{
public:NBAObserver(string name, Subject *sub) : Observer(name, sub){}void update() override{cout << name << " 收到消息:" << sub->event << endl;if (sub->event == "梁所长来了!"){cout << "我马上关闭NBA,装做很认真工作的样子!" << endl;}}
};int main()
{// 创建通知者Subject *dwq = new Secretary();// 被观察的对象Observer *xs = new NBAObserver("xiaoshuai", dwq);Observer *lm = new StockObserver("limin", dwq);// 加入观察队列dwq->attach(xs);dwq->attach(lm);// 事件dwq->event = "去吃饭了!";// 通知dwq->notify();cout << endl;// 事件dwq->event = "梁所长来了!";// 通知dwq->notify();cout << endl;return 0;
}

观察者为什么要和委托有联系?

  1. 抽象通知类还是依赖抽象观察者类
  2. 不同的被观察者可能并不相关,所以设计的接口不一定全都是一样的接口名称update.
    总结这两点,就是去除抽象观察者这个基类后,并且该更新状态的接口不同名的情况下,观察者模式仍旧可以成立。

何谓委托(大概了解即可)

委托是一种设计原则,指的是一个对象(委托者)将自身的一部分职责或功能交由另一个对象(被委托者)来执行。这种机制允许对象专注于自己的核心功能,同时利用外部对象的专业能力来完成辅助任务。委托强调的是行为的传递和执行,而不是对象所有权或生命周期的管理
在这里插入图片描述

那么,C++如何实现委托?

function+bind
参考:https://blog.csdn.net/qq_38410730/article/details/103637778
https://www.cnblogs.com/linuxAndMcu/p/14576162.html#_label1

# include <functional>
std::function<函数类型>

std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

# include <functional>
std::bind(函数指针, 绑定对象);

std::bind可以看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表

这样就可以实现:直接将具体观察者实例和观察者类状态更新接口函数(即之前的update)绑定。通知类管理的通知对象就从观察者实例变成了观察者的函数对象了。

也就是达到了:通知类不再依赖抽象观察者类的update接口,而是直接依赖这个绑定的函数对象。这样就可以达到:不需要抽象观察者类并且可以使用不同的接口名。

委托

参考:https://blog.csdn.net/weixin_43272766/article/details/94166777

  1. 去除了抽象观察者类
  2. 使用了C++的function+bind实现委托
#include <iostream>
#include <string>
#include <functional>
#include <list>
using namespace std;// 
typedef function<void()> Action;// 抽象观察者 无// 抽象通知者
class Subject
{
protected:list<Action *> actions;public:string event;virtual void attach(Action *a) = 0;virtual void detach(Action *a) = 0;virtual void notify() = 0;
};// 具体通知者,秘书
class Secretary : public Subject
{
public:void attach(Action *a) override{actions.push_back(a);}void detach(Action *a) override{actions.remove(a);}void notify() override{for (auto act : actions){(*act)();}}
};// 具体的观察者,看股票的
class StockObserver
{
private:string name;Subject *sub;public:StockObserver(string _name, Subject *_sub) : name(_name), sub(_sub){}void StockObserverUpdate(){cout << name << " 收到消息:" << sub->event << endl;if (sub->event == "梁所长来了!"){cout << "我马上关闭股票,装做很认真工作的样子!" << endl;}}
};// 具体的观察者,看NBA的
class NBAObserver
{
private:string name;Subject *sub;public:NBAObserver(string _name, Subject *_sub) : name(_name), sub(_sub){}void NBAObserverUpdate(){cout << name << " 收到消息:" << sub->event << endl;if (sub->event == "梁所长来了!"){cout << "我马上关闭股票,装做很认真工作的样子!" << endl;}}
};int main()
{// 创建通知者Subject *dwq = new Secretary();// 被观察的对象NBAObserver *xs = new NBAObserver("xiaoshuai", dwq);Action acA = bind(&NBAObserver::NBAObserverUpdate, xs);StockObserver *lm = new StockObserver("limin", dwq);Action acB = bind(&StockObserver::StockObserverUpdate, lm);// 加入观察者队列dwq->attach(&acA);dwq->attach(&acB);// 事件dwq->event = "去吃饭了!";// 通知dwq->notify();cout << endl;// 事件dwq->event = "梁所长来了!";// 通知dwq->notify();cout << endl;return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系万泰站长网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

解决Docker容器启动RabbitMQ报错:error pulling image configuration

解决Docker容器启动RabbitMQ报错&#xff1a;error pulling image configuration 问题原因是&#xff1a;Linux中系统时间跟真实时间相差太多导致。 解决办法就是让Linux的时间和网络时间同步就行了。 yum install -y ntpdate ntpdate 0.cn.pool.ntp.org

C# Winform 用户控件,扩展控件,自定义控件综合实例

Control类是Windows窗体控件的基类&#xff0c;它提供了在 Windows 窗体应用程序中进行可视显示所需的基础结构&#xff0c;可以通过继承来扩展熟悉的用户控件和现有控件的功能。本列介绍三种不同自定义控件以及怎么创建他们。 自定义控件分类 用户控件&#xff1a;基本控件的…

Go语言结构体内嵌接口

前言 在golang中&#xff0c;结构体内嵌结构体&#xff0c;接口内嵌接口都很常见&#xff0c;但是结构体内嵌接口很少见。它是做什么用的呢&#xff1f; 当我们需要重写实现了某个接口的结构体的(该接口)的部分方法&#xff0c;可以使用结构体内嵌接口。 作用 继承赋值给接口…

算法day31

第一题 542. 01 矩阵 本题本来求解的是每一个1到0的最短距离并返回到矩阵之中&#xff1b; 我们采用正难则反的思路&#xff0c;将其化解为每一个0到每一个1的最短距离&#xff0c;并通过矩阵来返回&#xff1b; 解法&#xff1a;多源bfs正难则反 步骤一&#xff1a; 定义一个…

笨蛋学算法之LeetCodeHot100_5_三数之和(Java)

package com.lsy.leetcodehot100;import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class _Hot6_三数之和 {public static List<List<Integer>> threeSum(int[] nums) {//先排序数组Arrays.sort(nums);//存放结果集List<Lis…

【Qt 学习笔记】Qt窗口 | 标准对话框 | 文件对话框QFileDialog

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt窗口 | 标准对话框 | 文件对话框QFileDialog 文章编号&#xff1a;Q…