C++设计模式二--OberverPattern(观察者模式)
来源:互联网 发布:ubuntu 设置ntp客户端 编辑:程序博客网 时间:2024/05/21 12:50
定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会收到通知并自动更新。
要点
1)观察者模式定义了对象之间的一对多的关系。
2)主题(被观察者)用一个共同接口(Observer)来更新观察者。
3)观察者和被观察者之间用松耦合方式结合,被观察者不知道观察者的细节,只知道观察者实现了观察者接口。
4)使用此模式,可以从被观察者车推(push)或拉(pull)数据(然而,推的方式被认为更“正确”)。
5)有多个观察者是,不可以依赖特定的通知次序。
类图
Subject:主题接口,对象使用此接口注册为观察者,或者把自己从观察者中删除。
Oberver:所有的观察者必须实现观察者接口,这个接口只有update()一个方法,当主题状态改变时会被调用。
ConcreteSubject:主题,必须实现主题接口的三个方法,当主题状态变化是通过notifyObserver()方法更新所有观察者。
concreteOberver:具体观察者,可以是实现此接口的任意类。观察者必须注册具体主题,以便接收更新。
设计原则
为了交互对象之间的松耦合设计而努力。
松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。
1)关于观察者,主题之知道观察者实现了某个接口(Observer接口)。主题不需要知道观察者的具体类是谁、做了写什么活着其他任何细节。
2)任何时候都可以增加新的观察者。
3)任何时候都可以删除或者取代某个或者某些观察者。
4)当有新的观察者出现时,主题代码不需要修改。只需要新的观察者实现此观察者接口(Observer接口),然后注册为观察者即可。
5)改变主题或观察者其中一方,并不影响另一方。因为两者是松耦合,只要他们之间的接口仍被遵守,我们就可以自由的改变他们。
示例
现在通过实现一个气象站示例。当气象站的状态发生变化是,需要通知不同的布告板来更新状态,如下为代码:
Subject.h
#ifndef SUBJECT_H#define SUBJECT_H#include "Observer.h"/*** 主题(被观察者)接口*/class Subject {public: virtual ~Subject(){} virtual void registerObserver(Observer* o) = 0; virtual void removeObserver(Observer* o) = 0; virtual void notifyObserver() = 0;};#endif
WeatherData.h
#ifndef WEATHERDATA_H#define WEATHERDATA_H#include "Observer.h"#include "Subject.h"#include <list>using namespace std;/*** 气象站(被观察者实例,一般只有一个)*/class WeatherData : public Subject {private: list<Observer*> m_observers; float m_temperature; float m_humidity; float m_pressure;public: WeatherData(){} void registerObserver(Observer* o) { m_observers.push_back(o); } void removeObserver(Observer* o) { // 从m_observers列表中删除o list<Observer*>::iterator i; for (i=m_observers.begin(); i!=m_observers.end(); i++) { if (*i == o) { m_observers.erase(i++); } } } void notifyObserver() { list<Observer*>::iterator i; Observer* observer; for (i=m_observers.begin(); i!=m_observers.end(); i++) { // 调用每一个观察者的update方法 observer = *i; observer->update(); } } float getTemperature() { return m_temperature; } float getHumidity() { return m_humidity; } float getPressure() { return m_pressure; } void measurementChanged() { notifyObserver(); } void setMeasurements(float temp, float humidity, float pressure) { this->m_temperature = temp; this->m_humidity = humidity; this->m_pressure = pressure; measurementChanged(); } // WeatherData的其他方法};#endif
Oberver.h
#ifndef OBSERVER_H#define OBSERVER_H/*** 观察者接口*/class Observer {public: virtual ~Observer(){} virtual void update() = 0;};#endif
CurrentConditionsDisplay.h
#ifndef CURRENTCONDITIONSDISPLAY_H#define CURRENTCONDITIONSDISPLAY_H#include "WeatherData.h"#include "Observer.h"#include "Subject.h"#include <iostream>using std::cout;/*** 显示目前状况(观察者实例,有多个)*/class CurrentConditionsDisplay : public Observer {private: float m_temperature; float m_humidity; Subject* m_weatherData; public: CurrentConditionsDisplay(Subject* weatherData) { this->m_weatherData = weatherData; weatherData->registerObserver(this); } void update() { WeatherData* weatherData = dynamic_cast<WeatherData*>(this->m_weatherData); if (weatherData) { this->m_temperature = weatherData->getTemperature(); this->m_humidity = weatherData->getHumidity(); display(); } } void display() { cout << "corrent conditions:"; cout << "temperature:" << m_temperature ; cout << " humidity:" << m_humidity << "%" << endl; }};#endif
TemperatureOnlyDisplay.h
#ifndef __TEMPERATUREONLYDISPLAY_H__#define __TEMPERATUREONLYDISPLAY_H__#include "WeatherData.h"#include "Observer.h"#include "Subject.h"#include <iostream>using std::cout;using std::endl;class TemperatureOnlyDisplay : public Observer{public: TemperatureOnlyDisplay(Subject* wd) { m_weatherData = wd; wd->registerObserver(this); } void update() { WeatherData* weatherData = dynamic_cast<WeatherData*>(this->m_weatherData); temp = weatherData->getTemperature(); display(); } void display() { cout << "TemperatureOnlyDisplay displaying, "; cout << "Temperuture: " << temp << endl; cout << endl; }private: Subject *m_weatherData; int temp; int humidity; int pressure;};#endif
main.cpp
#include <iostream>#include "WeatherData.h"#include "CurrentConditionsDisplay.h"#include "TemperatureOnlyDisplay.h"using namespace std;int main(){ WeatherData* weatherData = new WeatherData(); CurrentConditionsDisplay* currentDisplay = new CurrentConditionsDisplay(weatherData); TemperatureOnlyDisplay* temperatureDisplay = new TemperatureOnlyDisplay(weatherData); weatherData->setMeasurements(80, 65, 30.4); weatherData->removeObserver(currentDisplay); weatherData->setMeasurements(88, 55, 36.4); delete temperatureDisplay; delete currentDisplay; delete weatherData; return 0;}
Makefile
CXX = g++CFLAGS = -WallLDFLAGS = target = ressrcs = main.cppobjs = $(srcs:.cpp=.o).PHONY: allall: $(target)$(target): $(objs) $(CXX) $(LDFLAGS) -o $(target) $^$(objs):%.o:%.cpp $(CXX) $(CFLAGS) -c -o $@ $<clean: rm -f $(target) *.o
测试
测试结果如下所示:
本文完整代码下载地址:https://github.com/zhaoxd298/ObserverPattern
- C++设计模式二--OberverPattern(观察者模式)
- 设计模式二:观察者模式
- 设计模式二 观察者模式
- 设计模式二:观察者模式
- 设计模式之二---观察者设计模式
- java 设计模式之二-观察者模式
- 设计模式之观察者模式(二)
- 设计模式(二)Observer - 观察者模式
- 设计模式之二:观察者模式
- 设计模式之二:观察者模式
- 设计模式之二:观察者模式
- [设计模式as3版]二.观察者模式
- 设计模式-观察者模式(二)
- Java设计模式(二) 观察者模式
- 设计模式之观察者模式(二)
- 设计模式二之观察者模式
- 设计模式入门-观察者模式(二)
- 设计模式二之观察者模式
- 完成端口之个人理解
- 冒泡排序
- Nginx与tomcat组合的简单使用
- 网易新闻排行榜爬虫
- Android wifi模块
- C++设计模式二--OberverPattern(观察者模式)
- 向量的表示、投影、变换、协方差矩阵及PCA
- (二)hadoop配置虚拟机环境
- AndroidM及以上,接听电话之后5S 灭屏
- CRC校验
- ES6学习之路(六) Proxy 代理器&Reflect
- 带你玩转“数据卫士”Data Guard
- 服务器负载过高问题分析
- marker下报错Type Dynamic Web Module 3.1 requires Java 1.7 or newer.