c++ 设计模式5 (Observer / Event 观察者模式)

3.3 观察者模式 (Observer)/发布-订阅模式

动机:

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

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

代码示例: 文件分割器,添加处理过程进度展示功能。

第一种方法:

分析代码:违背依赖倒置原则

第6行: ProgressBar作为实现细节(表现形式可以多样变化,如图形界面,数字显示等)。其扮演的角色和任务是通知。

将通知的任务不用控件方式(太过细节)实现。

第二种方法:(重构第一种)

添加 IProgress类,作为抽象的通知机制,即观察者(订阅者)。观察者内含有更新方法DoProgress()。具体观察者(MainForm/ConsoleNotifier)继承该类,实现各自更新功能。

FileSplitter作为被观察对象(对象/发布者),其中含有抽象通知机制IProgress指针,利用DoProgress()方法进行通知。

即对象(发布者)不必考虑观察者情况,自动进行通知(发布)工作;

观察者(订阅者)根据自身实际情况选择是否订阅或如何处理通知。

同时考虑多个观察者问题添加List<IProgress*>。

 1 //FileSplitter1.cpp
 2 class FileSplitter
 3 {
 4     string m_filePath;
 5     int m_fileNumber;
 6     ProgressBar* m_progressBar;
 7
 8 public:
 9     FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) :
10         m_filePath(filePath),
11         m_fileNumber(fileNumber),
12         m_progressBar(progressBar){
13
14     }
15
16     void split(){
17
18         //1.读取大文件
19
20         //2.分批次向小文件中写入
21         for (int i = 0; i < m_fileNumber; i++){
22             //...
23             float progressValue = m_fileNumber;
24             progressValue = (i + 1) / progressValue;
25             m_progressBar->setValue(progressValue);
26         }
27
28     }
29
30 // MainForm1.cpp
31 class MainForm : public Form
32 {
33     TextBox* txtFilePath;
34     TextBox* txtFileNumber;
35     ProgressBar* progressBar;
36
37 public:
38     void Button1_Click(){
39
40         string filePath = txtFilePath->getText();
41         int number = atoi(txtFileNumber->getText().c_str());
42
43         FileSplitter splitter(filePath, number, progressBar);
44
45         splitter.split();
46
47     }
48 };

第二种方法:

 1 //FileSplitter2.cpp
 2 class IProgress{
 3 public:
 4     virtual void DoProgress(float value)=0;
 5     virtual ~IProgress(){}
 6 };
 7
 8
 9 class FileSplitter
10 {
11     string m_filePath;
12     int m_fileNumber;
13
14     List<IProgress*>  m_iprogressList; // 抽象通知机制,支持多个观察者
15
16 public:
17     FileSplitter(const string& filePath, int fileNumber) :
18         m_filePath(filePath),
19         m_fileNumber(fileNumber){
20
21     }
22
23
24     void split(){
25
26         //1.读取大文件
27
28         //2.分批次向小文件中写入
29         for (int i = 0; i < m_fileNumber; i++){
30             //...
31
32             float progressValue = m_fileNumber;
33             progressValue = (i + 1) / progressValue;
34             onProgress(progressValue);//发送通知
35         }
36
37     }
38
39
40     void addIProgress(IProgress* iprogress){
41         m_iprogressList.push_back(iprogress);
42     }
43
44     void removeIProgress(IProgress* iprogress){
45         m_iprogressList.remove(iprogress);
46     }
47
48
49 protected:
50     virtual void onProgress(float value){
51
52         List<IProgress*>::iterator itor=m_iprogressList.begin();
53
54         while (itor != m_iprogressList.end() )
55             (*itor)->DoProgress(value); //更新进度条
56             itor++;
57         }
58     }
59 };
60
61 //MainForm2.cpp
62 class MainForm : public Form, public IProgress
63 {
64     TextBox* txtFilePath;
65     TextBox* txtFileNumber;
66
67     ProgressBar* progressBar;
68
69 public:
70     void Button1_Click(){
71
72         string filePath = txtFilePath->getText();
73         int number = atoi(txtFileNumber->getText().c_str());
74
75         ConsoleNotifier cn;
76
77         FileSplitter splitter(filePath, number);
78
79         splitter.addIProgress(this); //订阅通知
80         splitter.addIProgress(&cn); //订阅通知
81
82         splitter.split();
83
84         splitter.removeIProgress(this);
85
86     }
87
88     virtual void DoProgress(float value){
89         progressBar->setValue(value);
90     }
91 };
92
93 class ConsoleNotifier : public IProgress {
94 public:
95     virtual void DoProgress(float value){
96         cout << ".";
97     }
98 };

定义:

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

类图:

Observer:  IProgress; Update():DoProgress() .

ConcreteSubject: FileSplitter

ConcreteObserver: Mainform / ConsoleNotifier

根据标准的Observer模式定义,也可将addIProgress,removeProgress,onProgress单独定义类(Subject),再将FileSplitter(ConcreteSubject)继承此类。

上述方法2 相当于将类图中的Subject 和 ConcreteSubject合二为一。

要点总结:

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

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

onProgress(progressValue);//发送通知,无需考虑具体的观察者问题。

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

79 splitter.addIProgress(this); //订阅通知

80 splitter.addIProgress(&cn); //订阅通知

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

 
时间: 2025-02-01 08:08:59

c++ 设计模式5 (Observer / Event 观察者模式)的相关文章

设计模式之 Observer Pattern 观察者模式

1.Subject通过一个容器保存零到多个Observer. 2.Subject通过Add,Delete方法调整Observer. 3.Subject的notifyObservers方法实际是逐个调用容器中Observer的notify方法.

C#设计模式之十六观察者模式(Observer Pattern)【行为型】

原文:C#设计模式之十六观察者模式(Observer Pattern)[行为型] 一.引言 今天是2017年11月份的最后一天,也就是2017年11月30日,利用今天再写一个模式,争取下个月(也就是12月份)把所有的模式写完,2018年,新的一年写一些新的东西.今天我们开始讲"行为型"设计模式的第四个模式,该模式是[观察者模式],英文名称是:Observer Pattern.还是老套路,先从名字上来看看."观察者模式"我第一次看到这个名称,我的理解是,既然有&quo

Head First设计模式之Observer

观察者模式定义对象之间的一对多的依赖,当那一个对象(主题)状态改变时,所有的依赖者(观察者)都会收到通知并作出相应的动作. 观察者模式的使用非常广泛. 代码实现: -------------------主题接口 public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); } --

Java设计模式(八)观察者模式 迭代器模式

(十五)观察者模式 观察者模式,定义对象间一对多关系,一个对象状态发生改变,所有依赖于它的对象都收到通知并且自动更新,观察者与被观察者分开.例如邮件订阅.RSS订阅,如果有更新就会邮件通知你. interface Observers{ public void update(); } class Observer1 implements Observers{ public void update(){ System.out.println("observer1 has received"

《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式

装饰者模式是JDK中另一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源码,也是为了学习大牛们的设计思路.----题记 设计模式 观察者模式:定义了对象之间一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新. 装饰者模式:动态地将责任附加到对象上.若要扩展功能,装饰者提供比继承者更有弹性的替代方案. 设计原则 (1)封装变化. (2)多用组合,少用继承. (3)针对接口编程,而不是

设计模式之二:观察者模式(Observer Pattern)

先看下观察者模式的定义: The Observer Pattern defines a one-to-many denpendency between objects so that when one object changes state, all of its dependents are notified and updated automatically.:观察者模式定义了对象间一对多依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新. 观察者模式又叫发布-

设计模式(行为型)之观察者模式(Observer Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(结构型)之代理模式(Proxy Pattern)>http://blog.csdn.net/yanbober/article/details/45480965 概述 观察者模式用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作

设计模式(二)The Observer Pattern 观察者模式

问题引入 生成一个公告板显示当时的天气状况,当天气状况发生改变的时候公告板能够实时的更新. 模式定义 定义对象之间的一对多的依赖.当一个对象改变状态时,它的全部依赖者都会自己主动收到通知并自己主动更新. 认识模式 该模式在生活中是非经常见的.想想生活中的各种各样的检測系统,报警系统,一旦有重要事件发生时,有关系统总能及时的收到通知.这就是观察者模式. 问题解决 关于观察者模式,java实际上给了我们内置的支持(能够看出该模式还是非经常常使用的吧!)可是我们经常会自己实现. 为什么呢?我们后面会给

[Android&amp;amp;Java]浅谈设计模式-代码篇:观察者模式Observer

观察者,就如同一个人,对非常多东西都感兴趣,就好像音乐.电子产品.Game.股票等,这些东西的变化都能引起爱好者们的注意并时刻关注他们.在代码中.我们也有这种一种方式来设计一些好玩的思想来.今天就写个Demo来描写叙述一下这种思想,用java内置的Observer来实现这一思想. 好,程序猿是不善言语的,看代码先. 1.demo的结构: 2.先创建我们的主题类Subject,他就是我们本demo的明星类.继承了Observable,顾名思义,就是被观察的类 .其它观察者对他但是虎视眈眈哦(事实上