[设计模式]行为模式-观察者(C++描述)

 [设计模式]行为模式-观察者(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. 后话

设计模式还有五六个,坚持写完所有的,加油。

 

 

猜你喜欢

转载自blog.csdn.net/second60/article/details/80312349