设计模式C++实现--Observer模式

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

介绍

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

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

实现

观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。

ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。

          观察者模式的 UML 图

步骤 1

创建 Subject 类。

// 被观察者
class Subject{
private:list<Observer *> _observers;int _state;public:int GetState(){return _state;}void SetState(int state){_state = state;NotifyAllObservers();}void Attach(Observer * observer){_observers.push_back(observer);}void NotifyAllObservers(){list<Observer*>::iterator iter = _observers.begin();for(;iter != _observers.end();iter++){(*iter)->update();}}
};

步骤 2

创建 Observer 类。


class Subject;class Observer{
protected:Subject * _subject;public:Observer(Subject *subject) : _subject(subject) {}virtual ~Observer(){}virtual void update() = 0;
};

步骤 3

创建实体观察者类。

class BinaryObserver : public  Observer{
public:BinaryObserver(Subject *subject) : Observer(subject) {_subject->Attach(this);}void update() override {std::cout << "Binary string :" << _subject->GetState() << std::endl;}
};class OctalObserver : public  Observer{
public:OctalObserver(Subject *subject) : Observer(subject) {_subject->Attach(this);}void update() override {std::cout << "Octal String:" << _subject->GetState() << std::endl;}
};class HexaObserver : public  Observer{
public:HexaObserver(Subject *subject) : Observer(subject) {_subject->Attach(this);}void update() override {std::cout << "Hex String:" << _subject->GetState() << std::endl;}
};

步骤 4

使用 Subject 和实体观察者对象。

    Subject * subject = new Subject();Observer * o1 = new BinaryObserver(subject);Observer * o2 = new OctalObserver(subject);Observer * o3 = new HexaObserver(subject);subject->SetState(1);subject->SetState(3);

步骤 5

验证输出。

Binary string :1
Octal String:1
Hex String:1
Binary string :3
Octal String:3
Hex String:3

 

 

 

转载于:https://my.oschina.net/fileoptions/blog/1823508

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

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

相关文章

Liunx 安装mysql 5.6.16

2019独角兽企业重金招聘Python工程师标准>>> 1.卸载原有的mysql 1)先查看原有的mysql rpm -qa|grep -i mysql 2)删除 mysql rpm -e --nodeps 包名 3)删除老版本 mysql的开发头文件和库 rm -fr /usr/lib/mysql rm -fr /usr/include/mysql 注意&#xff1a;卸载后/va…

java有效索引范围_Java索引超出范围:0

我拼命试图找出一种方法来阻止“字符串索引超出范围&#xff1a;0”错误……只要我不输入任何内容然后继续执行,就会发生这种情况&#xff1a;static String getRef(Scanner Keyboard){Scanner keyboard new Scanner(System.in);String ref "";boolean valid false…

UESTC 电子科大专题训练 DP-N

题意&#xff1a;有n个人写m行代码&#xff0c;第i个人写一行代码会产生ai个bug&#xff0c;问bug小于b的方案数 思路&#xff1a;背包二维费用 AC代码&#xff1a; #include "iostream" #include "string.h" #include "stack" #include "q…

HashMap与HashTable的区别

HashMap和HashSet的区别是Java面试中最常被问到的问题。如果没有涉及到Collection框架以及多线程的面试&#xff0c;可以说是不完整。而Collection框架的问题不涉及到HashSet和HashMap&#xff0c;也可以说是不完整。HashMap和HashSet都是collection框架的一部分&#xff0c;它…

数据挖掘 pandas基础入门之操作

为什么80%的码农都做不了架构师&#xff1f;>>> 统计 import pandas import numpy# 通过传递一个 numpyarray&#xff0c;时间索引以及列标签来创建一个DataFrame&#xff1a; dates pandas.date_range("20180509", periods6) df pandas.DataFrame(num…

C# Task.Delay()和Thread.Sleep()有什么区别?

很多时候我们需要做一段延时处理&#xff0c;就直接Thread.Sleep(n)处理了&#xff0c;但实际上延时也可以用Task.Delay(n)&#xff0c;那二者之间有没有区别呢&#xff1f;我们先来看一个案例&#xff1a;using System; using System.Threading; using System.Threading.Tasks…

java queue源码_java源码解读--queue

queue接口特点&#xff1a;可以模拟队列行为&#xff0c;即“先进先出”。接口结构queue接口继承了Collection接口&#xff0c;并增加了一些新方法12345678910111213141516public interface extends Collection{boolean add(E e);//将元素插入队列&#xff0c;如果失败返回fals…

旧题新做:从idy的视角看数据结构

“今天你不写总结……&#xff01;&#xff01;&#xff01;” 额…… 还是讲我的吧。这些考试都是idy出的题。 20170121&#xff1a;DFS序、 ST表、线段树练习 这是第一次考数据结构。 Problem 1. setsum 1 second    给你一个长度为N 的整数序列&#xff0c;支持两种操作…

常用的 Java 工具类之 Apache 全家桶使用

平常我们在日常的开发中会一些通用的功能封装成一些工具类&#xff0c;以便之后复用。但是有些常用功能&#xff0c;业界已经存在&#xff0c;我们无需造轮子&#xff0c;只需直接使用或借用它们的 Api &#xff0c;构建我们的自己项目中工具类。这篇首先介绍平常用到的 Apache…

.NET MAUI实战 MessagingCenter

1.概要在.NET MAUI提供了消息机制&#xff0c;该机制为订阅/发布模式。发布-订阅模式是一种消息传递模式&#xff0c;在此模式下&#xff0c;发布者可在无需知道任何接收方&#xff08;称为订阅方&#xff09;的情况下发送消息。同样&#xff0c;订阅方可在不了解任何发布方的情…

elasticsearch 5.1 问题 ubuntu

1、can not run elasticsearch as root 切换到非root用户 2、main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register") 改变elasticsearch文件夹所有者到当前用…

洛谷——P1033 自由落体

https://www.luogu.org/problem/show?pid1033#sub 题目描述 在高为 H 的天花板上有 n 个小球&#xff0c;体积不计&#xff0c;位置分别为 0&#xff0c;1&#xff0c;2&#xff0c;…&#xff0e;n-1。在地面上有一个小车&#xff08;长为 L&#xff0c;高为 K&#xff0c;距…

java 接口防刷_java轻量级接口限流/防刷插件

简介call-limit提供接口限流、防刷的功能&#xff0c;插件基于spring开发&#xff0c;在应用应用的任何一个逻辑层皆可使用(web、service、dao)&#xff0c;插件支持单机应用下的限流和分布式应用的限流(分布式应用限流需要依赖redis)&#xff0c;在简单业务场景下插件可为大家…

【leetcode】521. Longest Uncommon Subsequence I

题目如下&#xff1a; 解题思路&#xff1a;本题有点意思。首先如果输入的两个字符串都为空&#xff0c;那么结果是-1&#xff1b;如果两个字符串长度不一样&#xff0c;那么结果是较长的字符串的长度&#xff0c;因为较长的字符串肯定是自身的子序列&#xff0c;但一定不是较短…

【问题】为什么 System.Timers.Timer 更改间隔时间后的第一次触发时间是设定时间的三倍?...

【问题】为什么 System.Timers.Timer 更改间隔时间后的第一次触发时间是设定时间的三倍&#xff1f;独立观察员 2022 年 9 月 4 日在编写 “Wifi 固定器 [1]” 程序时&#xff0c;按如下方式使用了定时器&#xff1a;// 声明&#xff1b; private Timer _Timer new Timer() { …

JS魔法堂:判断节点位置关系

一、前言                           在polyfill querySelectorAll 和写弹出窗时都需要判断两个节点间的位置关系&#xff0c;通过jQuery我们可以轻松搞定&#xff0c;但原生JS呢&#xff1f;下面我将整理各种判断方法&#xff0c;以供日后查阅。 二…

ChartCtrl源码剖析之——CChartAxis类

CChartAxis类用来绘制波形控件的坐标轴&#xff0c;这个源码相对较复杂&#xff0c;当初阅读的时候耗费了不少精力来理解源码中的一些实现细节。 CChartAxis类的头文件。 #if !defined(AFX_CHARTAXIS_H__063D695C_43CF_4A46_8AA0_C7E00268E0D3__INCLUDED_) #define AFX_CHARTA…

java如何输出线程的标识符_Java多线程面试题

1、在Java中什么是进程&#xff0c;什么是线程进程&#xff1a;进程是程序执行的一个实例&#xff0c;进程是线程的容器。程序是指令、数据及其组织形式的描述&#xff0c;进程是程序的实体。线程&#xff1a;有时被称为轻量级进程(Lightweight Process&#xff0c;LWP)&#x…

基于.net开发的自助餐饮系统

本文系 EMQ&Intel 联合举办的首届“中国物联网数据基础设施最佳案例评选大赛“个人开发者赛道一等奖作品。项目简介智能餐饮自助结算系统是一个由称重系统、显示屏、自助扫码盒和 Intel CPU 组成的智能自助结算终端&#xff0c;将装有菜品的托盘放到秤盘上结算&#xff0c;…

cacti 被监控机器snmp 配置

被监控服务器 需要查看网卡流量&#xff0c; 磁盘空间等信息。修改如下。vi /etc/snmp/snmpd.conf1、找到com2sec notConfigUser default public 改为&#xff1a;com2sec notConfigUser 192.168.1.1&#xff08;改成监控服务器的ip&#xff09; public 2、找到…