博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式(15) - Observer观察者模式
阅读量:4071 次
发布时间:2019-05-25

本文共 4808 字,大约阅读时间需要 16 分钟。

目录


1.意图

  观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

2.UML类图

  

3.GOF角色说明  

Subject(目标)

  --目标知道它的观察者。可以有任意多个观察者观察同一个目标。
  --提供注册和删除观察者对象的接口。

Observer(观察者)

  --为那些在目标发生改变时需要获得通知的对象,定义一个更新接口。

ConcreteSubject(具体目标)

  --将有关状态存入各个ConcreteObserver对象。
  --当它的状态发生改变时,向它的各个观察者发出通知。

ConcreteObserver(具体观察者)

  --维护一个指向ConcreteSUbject对象的引用。
  --存储有关状态,这些状态应与目标的状态保持一致。
  --实现Observer的更新接口以使自身状态与目标的状态保持一致。

subject和observers之间定义为了一对多的关系。多个观察者依赖于某个目标,这样当目标的状态发生改变时,观察者就会被通知到。得到通知后,观察者就能使用新的值进行更新。

4.代码实现一

GoF版本:

#include
#include
#include
#include
#include
using namespace std;class Subject;class Observer{public: Observer() {} ~Observer() {} virtual void Update(Subject *theChangeSubject) = 0;};class Subject{public: Subject() {} virtual ~Subject() {} virtual void Attach(Observer *); virtual void Detach(Observer *); virtual void Notify();private: vector
_observers;};void Subject::Attach(Observer *ob){ _observers.push_back(ob);}void Subject::Detach(Observer *ob){ vector
::iterator pos = find(_observers.begin(), _observers.end(), ob); if (pos != _observers.end()) _observers.erase(pos);}void Subject::Notify(){ for_each(_observers.begin(), _observers.end(), [this](Observer *element) { element->Update(this); });}class ClockTimer :public Subject{public: ClockTimer() { _strtime_s(tmpbuf); } int GetHour(); int GetMinute(); int GetSecond(); void Tick();private: char tmpbuf[128];};//根据TZ环境变量来设置时区。如果TZ没有被设置,则查询操作系统//来获取默认值void ClockTimer::Tick(){ _tzset(); //获取系统风格的时间 _strtime_s(tmpbuf); Notify();}int ClockTimer::GetHour(){ char timebuf[128]; strncpy_s(timebuf, tmpbuf, 2); timebuf[2] = NULL; return atoi(timebuf);}int ClockTimer::GetMinute(){ char timebuf[128]; strncpy_s(timebuf, tmpbuf + 3, 2); timebuf[2] = NULL; return atoi(timebuf);}int ClockTimer::GetSecond(){ char timebuf[128]; strncpy_s(timebuf, tmpbuf + 6, 2); timebuf[2] = NULL; return atoi(timebuf);}class DigitalClock :public Observer{public: DigitalClock(ClockTimer *); ~DigitalClock(); void Update(Subject *); void Draw();private: ClockTimer *_subject;};DigitalClock::DigitalClock(ClockTimer *s) : _subject(s){ _subject->Attach(this);}DigitalClock::~DigitalClock(){ _subject->Detach(this);}void DigitalClock::Update(Subject *theChangedSubject){ int hour = _subject->GetHour(); int minute = _subject->GetMinute(); int sec = _subject->GetSecond(); cout << "Digital time is " << hour << ":" << minute << ":" << sec << endl;}class AnalogClock :public Observer{public: AnalogClock(ClockTimer *); ~AnalogClock(); void Update(Subject *); void Draw();private: ClockTimer *_subject;};AnalogClock::AnalogClock(ClockTimer *s) : _subject(s){ _subject->Attach(this);}AnalogClock::~AnalogClock(){ _subject->Detach(this);}void AnalogClock::Update(Subject *theChangedSubject){ if (theChangedSubject == _subject) Draw();}void AnalogClock::Draw(){ int hour = _subject->GetHour(); int minute = _subject->GetMinute(); int sec = _subject->GetSecond(); cout << "Analog time is " << hour << ":" << minute << ":" << sec << endl;}int main(){ ClockTimer timer; DigitalClock dc(&timer); AnalogClock ac(&timer); timer.Tick(); return 0;}

运行结果为:

Digital time is 20:9:14
Analog time is 20:9:14

5.代码实现二

与上一个例子不同之处在于,MySubject类与MyObserver类之间没有编译期间的依赖关系,而是在运行时动态创建的。

#include
#include
#include
#include
using namespace std;class Observer{public: virtual ~Observer(){} virtual void update(int message) = 0;};class Subject{public: virtual ~Subject() {} virtual void subscribe(Observer *); virtual void unsubscribe(Observer *); virtual void notify(int message);private: vector
_obsvList;};void Subject::subscribe(Observer *ob){ _obsvList.push_back(ob);}void Subject::unsubscribe(Observer *ob){ vector
::iterator pos = find(_obsvList.begin(), _obsvList.end(), ob); if (pos != _obsvList.end()) _obsvList.erase(pos);}void Subject::notify(int message){ for_each(_obsvList.begin(), _obsvList.end(), [message](Observer* element) { element->update(message); });}class MySubject : public Subject{public: enum message { ADD, REMOVE };};class MyObserver : public Observer{public: explicit MyObserver(const string &str) :_name(str) {} void update(int message) { cout << _name << " got message: " << message << endl; }private: string _name;};int main(){ MyObserver obA("observerA"); MyObserver obB("observerB"); MyObserver obC("observerC"); MySubject sub; sub.subscribe(&obA); sub.subscribe(&obB); sub.subscribe(&obC); sub.subscribe(&obB); sub.notify(MySubject::ADD); sub.notify(MySubject::REMOVE); getchar(); return 0;}

运行结果为:

observerA got message: 0
observerB got message: 0
observerC got message: 0
observerB got message: 0
observerA got message: 1
observerB got message: 1
observerC got message: 1
observerB got message: 1

 

你可能感兴趣的文章
ie下对于window.location.href的跳转时获取不到referer的,php中的路径包含有未定式的
查看>>
一段有用的jquery代码
查看>>
c#中队trunked的处理
查看>>
笔记本无线路由组件的局域网ping不通的问题
查看>>
php中require后的路径问题
查看>>
ext直接导出结果到excel
查看>>
combotree的总结
查看>>
最近小结
查看>>
大规模图像分类器的演化-Large-Scale Evolution of Image Classifiers-读后杂谈
查看>>
java对大文件的处理思路
查看>>
qt中的一个问题
查看>>
MFC编写的人民币大小写转换
查看>>
error C3861: “mciSendString”: 找不到标识符 的解决
查看>>
Process32First 返回FALSE的原因
查看>>
winform下的画图
查看>>
WordCloud简单实现效果图
查看>>
WordCloud基本算法
查看>>
java内存分配机制
查看>>
TensorFlow初入门
查看>>
目前我的问题
查看>>