设计模式之观察者模式

一  、基础观察者模式  

  观察者模式的定义是:

观察者模式(有时又被称为模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

    大概就是说在这个模式中有两种身份,一个是被观察的目标,另一个就是观察者,最简单的观察者模式就是观察者对目标有一份监听,当目标某些属性发生变化产生信号时,观察者能够知道并随之产生相应相关的变化。这种模式就像是收音机,被观察的目标就是电台,观察者就是收听的人,当电台收到新的信息之后会发出广播信号,收听者就能收到对应的信号并从中获取信息,并可以根据获取到的信息决定自己是否要作出反应,这就是最原始的观察者模式。

代码示例为:运行环境为VS2015

// 观察者练习.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <list>
using namespace std;

class  Observer
{
public:
	 Observer();
	~ Observer();
	virtual void UpData(int state) = 0;
private:

};

 Observer::Observer()
{
}

 Observer::~ Observer()
{
}

 class Listener : Observer
 {
 public:
	 Listener(int state);
	 ~Listener();
	 void UpData(int state);
	 void OutputState();
 private:
	 int m_Lstate;
 };

 void Listener::OutputState()
 {
	 cout << "当前监听者状态为:" << m_Lstate << endl;
 }

 Listener::Listener(int state)
 {
	 m_Lstate = state;
 }

 Listener::~Listener()
 {
 }

 void Listener::UpData(int state)
 {
	 m_Lstate = state;
	 return;
 }

class Subject
{
public:
	Subject();
	~Subject();
	virtual void Notify() = 0;
	virtual void Attach(Listener* lis) = 0;
	virtual void Detach(Listener* lis) = 0;
private:
};

Subject::Subject()
{
}

Subject::~Subject()
{
}

class Announcer : public Subject
{
public:
	Announcer();
	~Announcer();
	void Notify();
	void Attach(Listener* lis);
	void Detach(Listener* lis);

	void SetState(int state)
	{
		m_state = state;
	}
	int m_state;
private: 
	list<Listener *> m_ObsList;
};

Announcer::Announcer()
{
}

Announcer::~Announcer()
{
}

void Announcer::Attach(Listener* lis)
{
	m_ObsList.push_back(lis);
	return;
}

void Announcer::Detach(Listener* lis)
{
	m_ObsList.remove(lis);
	return;
}

void Announcer::Notify()
{
	list<Listener *>::iterator it = m_ObsList.begin();
	while (it != m_ObsList.end())
	{
		(*it)->UpData(m_state);
		++it;
	}
	return;
}

int main()
{
	Announcer* announcer = new Announcer();
	announcer->SetState(1);
	cout << "目标初始状态为:" << announcer->m_state << endl;
	
	Listener* listener1 = new Listener(0);
	Listener* listener2 = new Listener(0);

	cout << "监听者1:  ";
	listener1->OutputState();
	cout << "监听者2:  ";
	listener2->OutputState();

	announcer->Attach(listener1);
//	announcer->Attach(listener2);

	announcer->SetState(999);
	announcer->Notify();

	cout << "目标发生变化后" << endl;
	cout << "目标当前状态为:" << announcer->m_state << endl;

	cout << "监听者1:  ";
	listener1->OutputState();
	cout << "监听者2:  ";
	listener2->OutputState();

	delete listener1;
	listener1 = NULL;
	delete listener2;
	listener2 = NULL;
	delete announcer;
	announcer = NULL;

	system("pause");
    return 0;
}

运行结果为:

这就是最基础的观察者模式。

二、进阶的观察者模式

      上面的基础版的观察者模式主要是应用在简单的一对多的关系中,但是实际开发中还会有多对一、多对多等情况出现,这时我们可以通过对观察者模式进行升级来实现。之前的观察者模式中被监视的目标需要在自己发生变化后通知所有在自己这里注册了的观察者,这可能是一份很繁重的工作,所以我们可以为目标(Subject)添加一个助手来对自己的观察者(Observer)进行管理,这个助手我们将它命名为Manager。这个Manager就会取代 Subject 的位置,Observer 们不再与 Subject 有直接的联系,而是将自己的身份注册在Manager上。也就是将上面例子中的 Announcer 中的 关于 Listener 的列表被转移至了新增加的Manager类中,而Manager再将自己注册到Announcer 上,当 Announcer 产生了可能会改变 Listener 的信号,就将这个信号发送至Manager 上,Manager再将信号进行解析处理并通知对应的 Listener 进行处理。

       添加这个Manager的好处是可以用来解决多对多或是“不完全“”的一对多的关系的情况。多对多的情况下,Manager 可以通过自己所接收到的目标的信号来决定将信号发送给哪些监听者;“不完全“的一对多就是目标所产生的信号可能只对部分监听者有影响,就像你所收听到的天气广播只会是你所在的地区相关,并不一定对外地人有效,这时这个 Manager 可以记录哪些是与目标所发出的消息对应的“本地人”,而不再需要像基础的观察者模式中那样目标不管这个信号是否对监听者有影响,只会将信号发送给自己所拥有ID的监听者。这种添加了 Manager 后监听者模式使得目标中不必再保存很多的监听者名单,只要保留一个或几个 Manager 就可以,能够降低一些耦合度。

      可能有人会觉得这个 Manager 有没有都一样,监听者的名单注册在目标中也可以,只不过决定将信号转发给哪些监听者是由目标自己进行处理。确实是这样,这些对信号的处理放在目标中也是一样的,甚至这样可能开发时编写的代码会更少,但是如果目标是一个及其大的类,里面很多功能很多监听者,那么这些信号处理放在目标类中就会让目标类变得更难维护,添加了一个 Manager 可以使代码更加有条理,所以我还是觉得在监听者很多同时信号也有多种处理时添加一个 Manager 是不错的选择。

      这个进阶的观察者模式代码相比于上面的示例只是多了一个 Manager 类,有人看到这里还感兴趣的话可以自己去写一下。。。

 

    观察者模式作为开发中用的最多的设计模式之一还有很多值得研究的点,到现在我也只是初学,以后再对观察者模式有了进一步的思考再继续来更这一篇~~~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值