C++示例讲解观察者设计模式

目录
  • 引言
  • 什么是观察者设计模式
  • 解决的问题
  • 编程思路
  • 知识小百科

引言

用来解决两个不相关对象之间的一对一或者一对多的通信模型。

什么是观察者设计模式

观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主体是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接受通知。观察者模式不仅被广泛应用于软件界面元素之间的交互,在业务对象之间的交互、权限管理等方面也有广泛的应用。

解决的问题

定义了对象间的一种一对多的组合关系,以便一个对象的状态发生时,所有依赖于它的对象都得到通知并自动刷新。

观察者和被观察者之间存在“观察”的逻辑关系,当被观察者发生变化时,观察者就会观察到这样的变化,并作出相应的响应。

编程思路

设定两者类,一个为观察者类,一个为被观察者类

观察者类中,定义一个对某个事件感兴趣的处理函数,一般也叫做槽函数

被观察者类中,定义一个数据结构,用来保存观察者对某一个事件id(信号)感兴趣,使用数据结构建立信号与对象之间的映射关系

被观察者类中,定义两个方法函数:

一个方法为:添加观察者与其感兴趣的事件id(信号)加入到容器中

另一个方法为:信号函数:通知事件函数执行逻辑:首先遍历容器中,有没有感兴趣的事件ID,如果有,则代表一系列的观察者,对这个事件感兴趣,那么再次遍历观察者列表,让每一个观察者执行相应的槽函数

#include <iostream>
#include <map>
#include <list>
using namespace std;
class RecvBase
{
public:
    RecvBase()
    {
        cout << "RecvBase structure" <<  endl;
    }
    virtual void slotFunctions(int msgid)=0;
    virtual ~RecvBase()
    {
        cout << "RecvBase destruct" << endl;
    }
};
class Recv:public RecvBase
{
public:
    Recv()
    {
        cout << "Recv structure" << "---" << this << "---" << endl;
    }
    void slotFunctions(int msgid)override
    {
        switch(msgid)
        {
        case 1:
            cout << this << "接收到1信号,执行1信号对应的槽函数" << endl;
            break;
        case 2:
            cout << this << "接收到2信号,执行2信号对应的槽函数" << endl;
            break;
        case 3:
            cout << this << "接收到3信号,执行3信号对应的槽函数" << endl;
            break;
        case 4:
            cout << this << "接收到4信号,执行4信号对应的槽函数" << endl;
            break;
        }
    }
    ~Recv()override
    {
        cout << "Recv destruct" << endl;
    }
};
class Sender
{
public:
    Sender()
    {
        cout << "sender structure" << endl;
    }
    map<int,list<RecvBase* >> RecvMap;
    void observerToRecvMap(int msgid,RecvBase* recv)
    {
        this->RecvMap[msgid].push_back(recv);
    }
    void senderSignals(int msgid)
    {
        auto it = RecvMap.find(msgid);
        if(it!=RecvMap.end())
        {
            for(RecvBase* p:it->second)
            {
                p->slotFunctions(msgid);
            }
        }else{
            cout << "接收到未知信号,没有对应的可执行槽函数" << endl;
        }
    }
    ~Sender()
    {
        cout << "sender destruct" << endl;
    }
};
int main()
{
    Sender sender;
    RecvBase* r1=new Recv();
    RecvBase* r2=new Recv();
    RecvBase* r3=new Recv();
    RecvBase* r4=new Recv();
    sender.observerToRecvMap(1,r1);
    sender.observerToRecvMap(1,r2);
    sender.observerToRecvMap(2,r2);
    sender.observerToRecvMap(3,r3);
    sender.observerToRecvMap(4,r4);
    while(true)
    {
        int msgid;
        cin >> msgid;
        if(-1==msgid)break;
        sender.senderSignals(msgid);
    }
    delete r1;
    delete r2;
    delete r3;
    delete r4;
    return 0;
}

知识小百科

this指针:

  • 是本对象的起始地址,用const修饰的常地址(原型:stu *const this)(本文代码中this的作用)
  • 是隐藏在成员函数(非静态函数)的最左侧的常变量形参

作用:

  • 区别成员属性和成员函数的形参
  • 解引用,返回本对象的地址

到此这篇关于C++示例讲解观察者设计模式的文章就介绍到这了,更多相关C++观察者设计模式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++单例设计模式详细讲解

    目录 特殊类设计 只能在堆上创建对象的类 请设计一个类只能在栈上创建对象 请设计一个类不能被拷贝 请设计一个类不能被继承 请设计一个类只能创建一个对象(单例模式) 懒汉模式和饿汉模式的对比 特殊类设计 只能在堆上创建对象的类 请设计一个类,只能在堆上创建对象 实现方式: 将类的构造函数私有,拷贝构造声明成私有.防止别人调用拷贝在栈上生成对象. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建 class test { public: static test* GetObj() { re

  • C++设计模式之单例模式详解

    目录 单例模式:就是只有一个实例. 单例模式又分为两种基本的情形:饿汉式和懒汉式 如下是懒汉式单例类 小结: 继续看单例模式 总结 单例模式:就是只有一个实例. singleton pattern单例模式:确保某一个类在程序运行中只能生成一个实例,并提供一个访问它的全局访问点.这个类称为单例类.如一个工程中,数据库访问对象只有一个,电脑的鼠标只能连接一个,操作系统只能有一个窗口管理器等,这时可以考虑使用单例模式. 众所周知,c++中,类对象被创建时,编译系统为对象分配内存空间,并自动调用构造函数

  • C++设计模式之桥接模式(Bridge)

    桥接模式属于先天模式,这里的先天模式就是说一开始就要把结构搭建好,方便后来的扩展,而不是对已经出现的模块和接口进行改进扩展的.桥接的核心在于实体类和操作类之间的聚合关系,这个聚合关系就是我们所说的"桥",不同于装饰.代理和适配器模式的中的聚合关系,桥接不存在两者之间的继承关系,操作类是完全解耦的,而实体类对于操作类也只是弱耦合. 作用 将抽象部份与它的实现部份分离,使它们都可以独立地变化. 类视图 实现 //操作类 class action { public: virtual void

  • C++设计模式中控制反转与依赖注入浅析

    目录 控制反转 依赖注入(DI) 依赖注入框架(DI Framework) 依赖反转原则(DIP) 控制反转 “控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行.在使用框架之后,整个程序的执行流程可以通过框架来控制.流程的控制权从程序员“反转”到了框架. 大白话说,就是原先直接用main函数中的代码流程,转移到了框架中去. #include <iostream> #include <list> using namespace std

  • C++设计模式中的工厂模式详细介绍

    目录 1. 简单工厂模式 2. 工厂方法模式 3. 抽象工厂模式 1. 简单工厂模式 简单工厂模式(Simple Factory Pattern): 是指定义一个工厂类,工厂类中实现一个方法,此方法根据不同的参数返回不同的类,UML类图如下所示: 代码如下: #include <iostream> using namespace std; class Product { public: ~Product() {} // 纯虚函数 virtual void Create(string conte

  • C++设计模式迪米特法则实例

    迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话.英文简写为: LoD. 类的设计接口尽量封装完善,让外部直接调用 #include<iostream> #include<string> #include<vector> using namespace std; class AbstractBuilding { public: vi

  • C++实现设计模式之装饰者模式详解

    目录 设计模式和设计原则 装饰者模式中的类 案列描述 代码实现 总结 设计模式和设计原则 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者模式提供了比继承更有弹性的替代方案. 装饰者模式遵循的设计原则: 类应该对扩展开放,对修改关闭. 装饰者模式中的类 装饰者模式中的类如下图,C++设计模式之装饰模式 其中Component抽象组件类,即被装饰的类,每个组件都可以单独使用,或者被装饰者包起来使用.该类中声明了一些接口,这些接口将在具体组件,以及具体装饰者中实现. ConcreteComp

  • C++示例讲解观察者设计模式

    目录 引言 什么是观察者设计模式 解决的问题 编程思路 知识小百科 引言 用来解决两个不相关对象之间的一对一或者一对多的通信模型. 什么是观察者设计模式 观察者模式是一种对象行为模式.它定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.在观察者模式中,主体是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接受通知.观察者模式不仅被广泛应用于软件界面元素之间的交互,在业务对象之间的交互.权限管理等方面也有广泛

  • IOS观察者设计模式

    什么是观察者模式?我们先打个比方,这就像你订报纸.比如你想知道美国最近放生了些新闻,你可能会订阅一份美国周刊,然后一旦美国有了新的故事,美国周刊就发一刊,并邮寄给你,当你收到这份报刊,然后你就能够了解美国最新的动态.其实这就是观察者模式,A对B的变化感兴趣,就注册为B的观察者,当B发生变化时通知A,告知B发生了变化.这是一种非常典型的观察者的用法,我把这种使用方法叫做经典观察者模式.当然与之相对的还有另外一种观察者模式--广义观察者模式. 从经典的角度看,观察者模式是一种通知变化的模式,一般认为

  • WPF MVVM示例讲解

    在没给大家讲解wpf mwm示例之前先给大家简单说下MVVM理论知识: WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 我们使用模式,一般是想达到高内聚低耦合.在WPF开发中,经典的编程模式是MVVM,是为WPF量身定做的模式,该模式充分利用了WPF的数据绑定机制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,

  • jquery实现用户登陆界面(示例讲解)

    实例如下所示: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <script src="js/jquery-1.8.0.min.js"></script> <script> var cnresu = false; $(function(){

  • IKAnalyzer结合Lucene实现中文分词(示例讲解)

    1.基本介绍 随着分词在信息检索领域应用的越来越广泛,分词这门技术对大家并不陌生.对于英文分词处理相对简单,经过拆分单词.排斥停止词.提取词干的过程基本就能实现英文分词,单对于中文分词而言,由于语义的复杂导致分词并没英文分词那么简单,一般都是通过相关的分词工具来实现,目前比较常用的有庖丁分词以及IKAnalyzer等.这里我们主要通过一个简单的Demo聊聊IKAnalyzer的基本使用.IKAnalyzer是一个开源的,基于java开发的分词工具包,它独立于Lucene项目,同时提供了Lucen

  • PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)

    1.首先做主页面Ajax_pag.php 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Ajax做分页</title> <script src="bootstrap/js/jquery-1.11.2.min.js"></script> <script src="Ajax_

  • Sublime Text 3 实现C语言代码的编译和运行(示例讲解)

    Sublime Text 3是一款优秀的代码编辑软件.界面简洁,轻巧快速,很受大家的欢迎. 最近开始用他来编辑数据结构的代码,这就需要在新建编译系统. 具体方法如下: 首先: 接下来是关键的一步,将以下代码粘贴到弹出的编辑页面中,文件名为name.sublime-build形式,name是新建的编译器名字. { "cmd": ["gcc","${file}","-fexec-charset=gbk","-o"

  • 原生js封装运动框架的示例讲解

    昨天我们说了一下原生JS中常用的兼容性写法,今天我们来说一下运动框架. 正常情况下我们要写一个运动的效果会用到tween.js这么一个插件,这个东西不是一般人写出来的,因为里面涉及的运动效果都是经过一堆数学的函数运算出来的,我们平常人是写不出来的,所有我们就自己封装一个运动框架,有什么问题改起来也方便,下面我们就开始封装. 首先,我们先写一个div,设置一些简单的样式,我们就拿这个div举例子 如下代码: #div{ width: 100px; height: 100px; background

  • Python实现购物系统(示例讲解)

    要求: 用户入口 1.商品信息存在文件里 2.已购商品,余额记录. 商家入口 可以添加商品,修改商品价格 Code: 商家入口: # Author:P J J import os ps = ''' 1 >>>>>> 修改商品 2 >>>>>> 添加商品 按q为退出程序 ''' # 打开两个文件,f文件为原来存取商品文件,f_new文件为修改后的商品文件 f = open('commodit', 'r', encoding='utf-8

  • js数字滑动时钟的简单实现(示例讲解)

    废话不多说,直接上代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> body,ul{margin:0;padding: 0;} .content{margin:100px auto;wid

随机推荐