C++设计模式行为型之观察者模式

一、概述

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

二、示例代码

#include <list>

class Subject;

class Observer
{
public:
    virtual ~Observer();
    virtual void Update(Subject* theChangedSubject) = 0;
protected:
    Observer();
};

class Subject
{
public:
    virtual ~Subject(){}
    virtual void Attach(Observer* o)
    {
        _observers->push_back(o);
    }
    virtual void Detach(Observer* o)
    {
        _observers->remove(o);
    }
    virtual void Notity()
    {
        std::list<Observer*>::iterator it = _observers->begin();
        while (it != _observers->end())
        {
            (*it)->Update(this);
            ++it;
        }
    }
protected:
    Subject();
private:
    std::list<Observer*> *_observers;
};

上述代码是一个简单的观察者设计模式代码,逻辑清晰,但这种不能够通用,只能对特定的观察者才有效,即必须是Observer抽象类的派生类才行,并且这个观察者还不能带参数,而且接口参数不支持变化,那么观察者将不能应付接口的变化。那么应该如何解决这个问题呢?可以使用C++11一些特性来改变。

class NonCopyable
{
protected:
    NonCopyable() = default;
    ~NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete; //禁用拷贝构造
    NonCopyable& operator = (const NonCopyable&) = delete; //禁用赋值构造
};

#include <iostream>
#include <string>
#include <functional>
#include <map>

using namespace std;

template<typename Func>
class Events : NonCopyable
{
public:
    Events(){}
    ~Events(){}
    //注册观察者,支持右值
    int Connect(Func&& f)
    {
        return Assgin(f);
    }
    //注册观察者
    int Connect(Func& f)
    {
        return Assgin(f);
    }
    //移除观察者
    void Disconnect(int key)
    {
        m_connections.erase(key);
    }
private:
    //保存观察者并分配观察者编号
    template<typename F>
    int Assgin(F&& f)
    {
        int k = m_observerId++;
        m_connections.emplace(k, std::forward<F> (f));
    }
    int m_observerId = 0;
    std::map<int, Func> m_connections;
};

C++11实现的观察者,内部为了一个泛型函数列表,观察者只需要将观察者函数进行注册进来即可,消除了继承导致的强耦合。通知接口使用了可变参数模板,支持任意参数,这就消除了接口变化的影响。

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

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

相关文章

心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)

文章目录 前言介绍系统框架原项目地址本项目开发开源地址硬件PCB软件功能 详细内容硬件外壳制作WS2812级联及控制MAX30102血氧传感器0.96OLEDFreeRTOS 效果视频总结 前言 在好几年前&#xff0c;我好像就看到了焊武帝 jiripraus在纪念结婚五周年时&#xff0c;制作的一个心跳跟…

R语言中数据重塑(长宽表的转化)

学习笔记&#xff0c;仅供学习使用。 目录 1-什么是整洁的数据&#xff1f; 2-宽表变成长表 示例1&#xff1a; 示例2&#xff1a; 示例3&#xff1a; 3-长表变宽表 示例1&#xff1a; 示例2&#xff1a; 1-什么是整洁的数据&#xff1f; 按照Hadley的表述&#xf…

【redis】redis的认识和安装

目录 1.redis是什么2.Redis的特点3.安装redis4.设置远程连接4.1 开启隧道4.2 可视化客户端连接4.3 开启防火墙 5.redis常见数据类型5.1 redis的一些全局命令5.2 数据结构 6. redis的典型应用---缓存&#xff08;cache&#xff09;6.1 使用redis做缓存6.2 缓存穿透&#xff0c;缓…

华为VRP 系统基础配置

1.flash 相当于电脑的 硬盘 2.NVRAM 拿来专门存放系统配置文件 3.RAM 运行内存 4.ROM 系统引导 1.修改系统名[Huawei]sysname SWL1 2.配置登入信息 [SWL1]header shell information "Welocom to the learning" [SWL1]q <SWL1>q User interface con0 …

Excel·VBA表格横向、纵向相互转换

如图&#xff1a;对图中区域 A1:M6 横向表格&#xff0c;转换成区域 A1:C20 纵向表格&#xff0c;即 B:M 列转换成每2列一组按行写入&#xff0c;并删除空行。同理&#xff0c;反向操作就是纵向表格转换成横向表格 目录 横向转纵向实现方法1转换结果 实现方法2转换结果 纵向转横…

《吐血整理》高级系列教程-吃透Fiddler抓包教程(30)-Fiddler如何抓Android7.0以上的Https包-番外篇

1.简介 通过宏哥前边几篇文章的讲解和介绍想必大家都知道android7.0以上&#xff0c;有android的机制不在信任用户证书&#xff0c;导致https协议无法抓包。除非把证书装在系统信任的证书里&#xff0c;此时手机需要root权限。但是大家都知道root手机是非常繁琐的且不安全&…

HDFS中的sequence file

sequence file序列化文件 介绍优缺点格式未压缩格式基于record压缩格式基于block压缩格式 介绍 sequence file是hadoop提供的一种二进制文件存储格式一条数据称之为record&#xff08;记录&#xff09;&#xff0c;底层直接以<key, value>键值对形式序列化到文件中 优…

Android随笔-VPN判断

Android中判断当前网络是否为VPN /*** 判断当前网络是否为VPN* param context* return*/public static boolean hasVPN(Context context) {// 查询网络状态&#xff0c;被动监听网络状态变化ConnectivityManager cm (ConnectivityManager) context.getSystemService(Context.C…

动态规划(一)

一、背包问题 1.1 01背包问题 特点:每件物品最多只用于一次 属性包括:最大值(Max)、最小值(Min)、数量 #include<iostream> #include<algorithm>using namespace std;const int N 1010;int n,m; int v[N],w[N]; int f[N][N];int main() {cin>>n>>m;…

bash shell 中的特殊字符详解

bash shell 中的特殊字符详解 [sharp] # 井号 井号常用作注释符号 1.注释示例 # This line is a comment.2.某命令后注释&#xff0c;#号前需要添加一个空格 echo "A comment will follow." # Comment here. # ^ Note whitespace bef…

hive中时间戳与时间字符串相互转换的方法教程

时间戳是数据库常用的存放日期的形式之一&#xff0c;表示从 UTC 时间’1970-01-01 00:00:00’开始到现在的秒数&#xff0c;与常规时间格式如 ‘2018-01-01 00:00:00’可以相互转换&#xff0c;方法如下。 一、unix_timestamp 函数用法 1、unix_timestamp() 返回当前时间戳。…

Java通过实例调用getClass()方法、类名.class操作、通过运行时类获取其它信息

说明 Java Object类的getClass()函数&#xff0c;是通过对象调用的&#xff0c;是一个实例方法&#xff0c;该方法返回当前对象的运行时类。 通过类名.class可以获得和通过实例调用getClass()函数一样的信息。 获得运行时类以后&#xff0c;可以进一步获取其它信息。 代码示例…

MyCat概述

1.MyCat概述 MyCat是阿里巴巴的产品&#xff0c;他是开源的、基于Java语言编写的MySQL数据库中间件。可以像使用mysql一样来使用mycat&#xff0c;对于开发人员来说根本感觉不到mycat的存在。 MyCat下载地址&#xff1a;http://dl.mycat.org.cn/ MyCat官网&#xff1a;http:/…

CuratorFramework接口的作用和使用

CuratorFramework接口是Apache Curator库中的核心接口之一&#xff0c;用于与ZooKeeper集群进行交互。它提供了一组丰富的方法和功能&#xff0c;用于简化与ZooKeeper的交互操作&#xff0c;包括创建、删除、读取和更新节点等。 CuratorFramework接口的主要作用是封装了底层与…

【C语言进阶篇】模拟实现通讯录 (内附源码)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言一 、 通讯录的简介1.1 联系人的类型定义1.2 通讯录的定义1.3 通讯录要实现的功能 二 、 如何…

计算机网络的定义和分类

计算机网络的定义和分类 计算机网络的定义 计算机网络的精确定义并未统一计算机网络最简单的定义是&#xff1a;一些互相连接的、自治的计算机的集合 互连:指计算机之间可以通过有线或无线的方式进行数据通信自治:是指独立的计算机&#xff0c;它有自己的硬件和软件&#xff…

Python语法:... for ... in ... if ...

Python中&#xff0c;for...in...[if]...语句是一种简洁的构建List的方法&#xff0c;从for给定的List中选择出满足if条件的元素组成新的List&#xff0c;其中if是可以省略的。下面举几个简单的例子进行说明 [for in ]: ...for ....in..... 语句. 实例如下&#xff1a; (1) …

Ubuntu出现内部错误解决办法

使用的Ubuntu版本是18.04&#xff0c;使用的时候弹出对话框说出现了内部错误&#xff0c;好奇是哪里出现了错误&#xff0c;查找了一下解决的办法&#xff0c;记录一下。 参考解决方案&#xff1a;ubantu出现了内部错误 一旦程序崩溃过一次&#xff0c;就会生成一个.crash文件…

PHP实现首字母头像

<?php $name"哈哈"; $logoletter_avatar($name);echo <img src".$logo." style" border-radius: 50%;">;function letter_avatar($text) {$total unpack(L, hash(adler32, $text, true))[1];$hue $total % 360;list($r, $g, $b) hs…

Centos系统有哪些特点呢

CentOS 是一个基于 Red Hat Enterprise Linux (RHEL) 的免费的开源操作系统,由 CentOS 项目维护。CentOS 项目是一个社区驱动的项目,旨在为用户提供一个稳定的、可扩展的 Linux 发行版。 CentOS 系统具有以下特点: 稳定性:CentOS 系统非常稳定,即使是在高负载的环境下也是如此…