[设计模式]行为模式-观察者(C++描述)
second60 20180514
1. 什么是观察者模式
打个比方,一个表演者在台上表演,台下有很多观众在观看。当台上的表演者,每做一个动作,台下的观众都可以看到。这里的观众就是观察者。
定义对象间一对多的依赖,当(表演者)一个对象状态改变时,所有依赖它的对象(观众)都得到通知并更新。
观察都模式解决的问题:建立一个Subect对多个Observer的依赖关系,当subject变化时,依赖subject的观察都都会同步改变.
2. 观察都模式结构图
分析:
1. Subject: 主题,需要观察都订阅的主题抽象类,里面包含需要通知的观察都列表
2. ConcretetSubject: 具体主题
3. Observer: 观察者抽象父类,包含通知更新的方法
4. ConcreteObserverA/ConcreteObserverB: 具体的观察都
代码:
#include "stdafx.h" #include <string> #include <list> #include <iostream> using namespace std; typedef string State; class Subject; // 观察都父类 class Observer { public: Observer(){ _state = ""; } ~Observer(){} virtual void update(Subject* sub) = 0; State _state; }; // 主题抽象父类,只包含观察者和观察者的方法 // 具体的数据是放在实现类中 // 这里的State可以是一个模型的父类,具本什么模型,由子类去决定和操作 class Subject { public: Subject(){ _obverser = new std::list < Observer* > ; } ~Subject(){ /*释放obverser*/ } virtual void attach(Observer* obv){ _obverser->push_front(obv); } virtual void detach(Observer* obv){ if (obv != NULL) _obverser->remove(obv); } virtual void notify() { std::list<Observer*>::iterator iter = _obverser->begin(); for (; iter != _obverser->end(); ++iter) { (*iter)->update(this); } } virtual void setState(const State &st) = 0; virtual State getState() = 0; private: std::list<Observer*> *_obverser; }; class ConcreteSubject : public Subject { public: ConcreteSubject(){} ~ConcreteSubject(){} State getState(){ return _state; } void setState(const State& state){ _state = state; } protected: State _state; }; class ObserverA : public Observer { public: ObserverA(Subject *sub) { _sub = sub; _sub->attach(this); } ~ObserverA() { _sub->detach(this); if (_sub) delete _sub; } void update(Subject* sub) { _state = sub->getState(); std::cout << "ObserverA::state=" << _state << std::endl; } private: Subject *_sub; }; class ObserverB : public Observer { public: ObserverB(Subject *sub) { _sub = sub; _sub->attach(this); } ~ObserverB() { _sub->detach(this); if (_sub) delete _sub; } void update(Subject* sub) { _state = sub->getState(); std::cout << "ObserverB::state=" << _state << std::endl; } private: Subject *_sub; }; int _tmain(int argc, _TCHAR* argv[]) { // 主题 ConcreteSubject *sub = new ConcreteSubject(); // 观察者监主题 Observer* observer1 = new ObserverA(sub); Observer* observer2 = new ObserverB(sub); // 主题修改,通知所有观察都 sub->setState("old"); sub->notify(); // 主题修改,通知所有观察都 sub->setState("new"); sub->notify(); getchar(); return 0; }
3. 观察者模式用途
观察都模式,我们平时很常用,MVC(model/view/control)模式,一说大家都用过吧。
其实他就是观察都模式的一种。
model: 就是上面的subject
view: 就是上面的观察都,可能有多个不同的观察者
observer模式,也称为发布-订阅模式,目前很多系统都运用了这种模式,如kfak,redis等,只需向系统订阅需要监听的信息,发送信息的只管发送。订阅都只接收自已感兴趣的信息。
适用场景:
1. 一对多依赖,如果一改变,需要通知到多的场景,双方无须了解对方细节
2. MVC场景
3. 订阅 - 发布场景
4. 举例子
观察者模式中MVC是一种非常常用的例子。举个客户端的例了。代码就不写了。
如游戏客户端中的玩家金币信息, 当服务端推送来玩家金币信息时,客户端要通知很多view中有金币相关的界面。如大厅/个人信息/游戏玩家信息等。所以只需监听玩家需要监听的信息,并通知相关的view即可。
分析:
当服务端推送的玩家金币改变时,会自动通知监听的view更新玩家金币信息.
这里只是单个例子,实际运用中,包括很多玩家属性要通知的,这里就列举了。
5. 优缺点
5.1 优点
1. 观察者和主题之间是松耦合,观察都新加删除逻辑,无需改动主题类。
2. 主题只需通知观察者,至于观察者后面想做什么,主题无须了解细节。
3. 只要订阅主题的观察者,都会实时的通知到(主题主动通知,观察都只需等待被更新即可)。如果观察者主动获取,确定不准备时机,而且不能确保有所以观察者都会及时更新。造成信息不同步问题。
4. 符合面向对象开放-封闭原则,有良好的扩展性和维护性
5.2 缺点
1. 观察删除问题,如果主题删除,相应的观察都也要一并删除;
2. 如果是用指针来维护数据,要记得多引用时指针的释放问题
6. 总结
观察者模式,是一个很好的设计模式,符合面向对象开放-封闭原则,有良好的维护和扩展性,现实中运用非常广泛,大系统或框架设计时,或多或少都会用到,所以要善于运用。
7. 后话
设计模式还有五六个,坚持写完所有的,加油。