C++设计模式(观察者模式)

news/2024/12/5 0:35:42 标签: 设计模式, 观察者模式, c++

一、介绍

1.动机

在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”,即一个对象的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。

使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系,从而实现软件体系结构的松耦合。

 

2.定义

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。——GOF

 

3.结构图

731dce10adda49c98474d68fe62136a3.jpeg

 

4.要点总结

使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。

目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。

观察者自己决定是否需要订阅通知,目标对象对此一无所知。

Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。

 

 

二、观察者模式

1.概念

观察者模式的核心在于观察者向被观察者注册,当被观察者状态发生变化时,通知观察者更新。实现时可以使用容器类来管理观察者列表,以便在状态变化时能够遍历并通知所有观察者。

①优点:

  • 实现了松散耦合,观察者和被观察者之间没有直接的依赖关系。
  • 支持广播通信,一个对象的状态变化可以轻松地通知所有观察者对象。

②缺点:

  • 如果观察者对象过多,可能会影响程序的性能。
  • 如果观察者和被观察者之间有循环依赖的话,可能会导致系统崩溃。

 

2.实现要点

 

  • 抽象观察目标:维护一个观察者列表,提供添加、删除和通知观察者的接口。
  • 具体观察目标:实现抽象观察目标提供的接口,当状态改变时,通知所有观察者。
  • 抽象观察者:定义一个抽象观察者类,其中包含一个更新接口。
  • 具体观察者:实现更新接口,以便在收到通知时更新自身状态。

 

3.示例

//观察者(抽象类)
class Observer {
public:
    virtual void update(const string& news) = 0;
    virtual ~Observer() {}
};

//发布者(抽象观察目标)
class Publisher {
public:
    virtual void attach(Observer* obs) = 0;
    virtual void detach(Observer* obs) = 0;
    virtual void notify(const string& news) = 0;
    virtual ~Publisher() {}
};

//新闻发布者(具体观察目标)
class NewsPublisher :Publisher {
private:
    list<Observer*> newsList;
public:
    virtual void attach(Observer* obs) override {
        newsList.push_back(obs);
    }
    virtual void detach(Observer* obs) override {
        newsList.remove(obs);
    }
    virtual void notify(const string& news) override {
        for (auto obs : newsList) {
            obs->update(news);
        }
    }
};

//年轻人(具体观察者)
class YoungPeople :public Observer {
private:
    string name;
    int age;
public:
    YoungPeople(const string& n, int a)
        :name(n), age(a) {}
    virtual void update(const string& news) override {
        cout << "Young people " << name << " " << age << " " << news << endl;
    }
};

//中年人(具体观察者)
class MiddleAgedPeople :public Observer {
private:
    string name;
    int age;
public:
    MiddleAgedPeople(const string& n, int a)
        :name(n), age(a) {}
    virtual void update(const string& news) override {
        cout << "Mid-aged people " << name << " " << age << " " << news << endl;
    }
};

测试代码:

NewsPublisher news_publisher;
YoungPeople* p1 = new YoungPeople("Alice", 15);
YoungPeople* p2 = new YoungPeople("Bob", 20);
MiddleAgedPeople* p3 = new MiddleAgedPeople("Charlie", 40);
MiddleAgedPeople* p4 = new MiddleAgedPeople("David", 45);

news_publisher.attach(p1);
news_publisher.attach(p2);
news_publisher.attach(p3);
news_publisher.attach(p4);
news_publisher.notify("Initial news");
cout << endl;
news_publisher.detach(p2);
news_publisher.detach(p4);
news_publisher.notify("Subsequent news");

delete p1;
delete p2;
delete p3;
delete p4;

输出结果:

Young people Alice 15 Initial news
Young people Bob 20 Initial news
Mid-aged people Charlie 40 Initial news
Mid-aged people David 45 Initial news

Young people Alice 15 Subsequent news
Mid-aged people Charlie 40 Subsequent news

 

 

 


http://www.niftyadmin.cn/n/5768051.html

相关文章

深度学习1:从图像识别到自动驾驶:深度学习如何引领未来出行新趋势?

文章目录 导读一、机器学习与经验积累&#xff1a;一场智慧的碰撞二、深度学习的四大基石&#xff1a;数据模型目标函数与算法三、深度学习的应用场景&#xff1a;从多标签分类到强化学习四、深度学习的发展历程&#xff1a;从“重新发现”到“寒武纪大爆发”五、深度学习的成功…

无人机数据处理系统:原理与核心系统

一、数据处理系统的运行原理 数据获取&#xff1a;无人机在飞行过程中&#xff0c;通过搭载的传感器&#xff08;如相机、激光雷达等&#xff09;采集到各种类型的数据&#xff0c;例如图像、点云等。这些数据是后续处理和分析的基础。 数据传输&#xff1a;采集到的数据会通…

VSCode中“Run Code”运行程序时,终端出现中文乱码解决方法

问题描述 在VSCode中“Run Code”运行程序时&#xff0c;终端输出结果出现中文乱码现象&#xff1a; 解决方法 1. 检查系统cmd的默认编码 查看Windows终端当前编码方式的命令&#xff1a; chcp输出结果是一段数字代码&#xff0c;如936&#xff0c;这说明当前的cmd编码方式…

LinkedList的了解

一、LinkedList的定义与类型 Java中的LinkedList类是一个双向链表&#xff08;Doubly Linked List&#xff09;。与单向链表&#xff08;Singly Linked List&#xff09;不同&#xff0c;双向链表中的每个节点不仅包含指向下一个节点的引用&#xff0c;还包含指向前一个节点的…

探索文件系统,Python os库是你的瑞士军刀

文章目录 探索文件系统&#xff0c;Python os库是你的瑞士军刀第一部分&#xff1a;背景介绍第二部分&#xff1a;os库是什么&#xff1f;第三部分&#xff1a;如何安装os库&#xff1f;第四部分&#xff1a;简单库函数使用方法1. 获取当前工作目录2. 改变当前工作目录3. 列出目…

【系统架构设计师】高分论文:论信息系统的安全与保密设计

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 摘要正文摘要 本人所在工作单位承担了我市城乡智慧建设工程综合管理平台项目的开发工作。我有幸参与了本项目,并担任架构师一职,全面负责项目的需求分析和系统设计等工作。城乡智慧建设工程综合管理平台项目包括…

03-11、SpringCloud第十一章,升级篇,分布式链路跟踪Sleuth

SpringCloud第十一章&#xff0c;升级篇&#xff0c;分布式链路跟踪Sleuth 一、分布式链路概述 1、为什么 随着分布式系统越来越复杂&#xff0c;你的一个请求发过发过去&#xff0c;各个微服务之间的跳转&#xff0c;有可能某个请求某一天压力太大了&#xff0c;一个请求过…

基于若依框架和Vue2 + Element-UI 实现图片上传组件的重写与优化

背景 在使用 若依分离版Element-UI 的图片上传组件时,需要根据业务需求进行定制化处理,比如: 需要传递额外的业务参数到后端需要对上传路径进行修改需要对上传组件进行样式定制 实现步骤 1. 创建本地组件 首先在业务模块下创建本地的图片上传组件: src/views/xxx/compone…