第二章 观察者模式
来源:互联网 发布:pcb 合拼算法 编辑:程序博客网 时间:2024/06/08 03:22
定义
观察者模式定义了对象之间一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
设计原则
为了交互对象之间的松耦合设计而努力。松耦合的设计之所以能让我们建立有弹性的OO系统,能够应付变化,是因为对象之间的互相依赖降到了最低。
代码实现
需求
有一个天气采集器,能够采集温度、湿度和气压,实现一个主题系统,该系统能够接受多个app的订阅,在采集器信息改变时,系统会获取到新的信息,并通知订阅的app,app则会将新数据展示出来。
分析
主题系统虽然可以在类的属性中添加每一个订阅者,但是这是在编译期决定的,没法在运行期动态添加订阅者,每当新添加或者删除一个订阅者的时候都需要改动类的代码并重新编译,这样不具备弹性,如果能将订阅者的添和删除放到运行期来做,这样就不需要改动类的代码,对象依赖就降低了。
// Subject.h#pragma once#include <iostream>#include <memory>#include <vector>#include <algorithm>#define CLASS_MEMBER_VAR(type, name) \ public: \ void set_##name(type name) { name##_ = name; } \ type name() const { return name##_; } \ protected: \ type name##_;class Subject;class Observer;typedef std::shared_ptr<Subject> SubjectPtr;typedef std::shared_ptr<Observer> ObserverPtr;class Subject {public: typedef std::vector<ObserverPtr> ObserverList; Subject(); void registerObserver(ObserverPtr o) { observers_.push_back(o); printf("Subject: register observer:%p done.\n", o.get()); } void removeObserver(ObserverPtr o) { auto pos = std::find_if(observers_.begin(), observers_.end(), [o](ObserverPtr ptr) { return ptr.get() == o.get(); }); if (pos != observers_.end()) { observers_.erase(pos); printf("Subject: remove observer:%p done.\n", o.get()); } } void notifyObservers();private: ObserverList observers_; CLASS_MEMBER_VAR(double, temperature); CLASS_MEMBER_VAR(double, pressure); CLASS_MEMBER_VAR(double, humidity);};
// Subject.cpp#include "Subject.h"#include "Observer.h"Subject::Subject() : temperature_(1.23), pressure_(4.56), humidity_(7.89){}void Subject::notifyObservers() { // observer will pull data for (auto& o : observers_) { o->update(); }}
// Observer.h#pragma once#include <memory>#include <vector>#include <iostream>class Subject;class Observer;typedef std::shared_ptr<Subject> SubjectPtr;typedef std::shared_ptr<Observer> ObserverPtr;class Observer : public std::enable_shared_from_this<Observer> {public: Observer(SubjectPtr subject); virtual ~Observer() { } virtual void update() = 0; virtual void display() = 0;protected: SubjectPtr subject_;};class Observer1 : public Observer {public: Observer1(SubjectPtr subject); void update() override; void display() override;};class Observer2 : public Observer {public: Observer2(SubjectPtr subject); void update() override; void display() override;};
// Observer.cpp#include "Observer.h"#include "Subject.h"Observer::Observer(SubjectPtr subject) : subject_(subject){}Observer1::Observer1(SubjectPtr subject) : Observer(subject){}void Observer1::update() { printf("Observer1: received update from Subject.\n"); display();}void Observer1::display() { printf("Observer1: pull data from Subject and display it.\n"); printf("\ttemperature: %lf\n", subject_->temperature()); printf("\thumidity: %lf\n", subject_->humidity()); printf("\tpressure: %lf\n", subject_->pressure());}Observer2::Observer2(SubjectPtr subject) : Observer(subject){}void Observer2::update() { printf("Observer2: received update from Subject.\n"); display();}void Observer2::display() { printf("Observer2: pull data from Subject and display it.\n"); printf("Observer2(%p): remove from Subject.\n", this); subject_->removeObserver(shared_from_this());}
// main.cpp#include "Subject.h"#include "Observer.h"using namespace std;int main(int argc, char** argv) { SubjectPtr subject(new Subject()); ObserverPtr observer1(new Observer1(subject)); subject->registerObserver(observer1); ObserverPtr observer2(new Observer2(subject)); subject->registerObserver(observer2); subject->notifyObservers(); return 0;}
// Makefileall: observerobserver: main.cpp Observer.cpp Subject.cpp c++ -g -std=c++11 -o $@ $^clean: -rm -rf observer
不得不说,即便是C++11,在使用上依旧缺陷重重,本章在代码实现过程中碰到几个特别烦人的问题:
1、先声明再使用的规定极大地限制了代码的简洁性,违反了DRY原则,降低了封装性,弊大于利。对象互相调用对方的方法时,比如A调用B的方法fb(), B调用A的方法fa(),代码若在同一个文件内实现会很蹩脚。
2、构造函数内能做的事情极其有限。我想在Observer类的构造函数里面将该对象注册到Subject对象之中去,由于需要传递当前对象的shared_ptr,但是在构造函数里无法获得当前对象的shared_ptr,即便让该类继承enable_shared_from_this也不行,为此,不得不将初始化工作分成两步,在构造函数之外进行注册,这样极大地降低了代码的封装性。另外在使用shared_from_this()的时候必须要确保对象在堆上且引用计数不为0,否则会抛出异常。
以上问题在Java里面根本不存在!
- 第二章 观察者模式
- 第二章 观察者模式
- 第二章 观察者模式1
- 第二章 观察者模式2
- HeadFirst设计模式第二章 观察者模式
- 设计模式---第二章观察者模式
- HeadFirst设计模式第二章(观察者模式Observer)
- Head First设计模式第二章——观察者模式
- 观察者模式-《Head First 设计模式》第二章
- [设计模式]head first 设计模式之PHP实现 第二章 观察者模式
- Head First设计模式C++实现--第二章:观察者(Oserver)模式
- 设计模式第二课:观察者模式(Obse…
- 设计模式第二天_观察者模式_java内置实现
- 设计模式C++版:第二十一式观察者模式
- Project第二天 观察者模式处理定位信息
- 观察者模式
- 观察者模式
- 观察者模式
- 关于“Could not open ServletContext resource [/WEB-INF/applicationContext.xml]”解决方案
- nodejs处理页面跳转url地址的处理
- 资源 | 数十种TensorFlow实现案例汇集:代码+笔记【转】
- JavaScript中的数组
- TreeMap put(K key,V value)源码分析
- 第二章 观察者模式
- Java线程池
- 动态规划LCIS
- Java8<使用流API优雅地将int[]转换为ArrayList>
- seaweedfs安装、启动
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- RMQ----不更新点
- JSON序列化
- 单向链表的构造