观察者模式-对象行为模式

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

动机:将一个系统分割成一系列相互协作的类有一个副作用:需要维护相关对象间的一致性。不希望为了维持一致性而使各类紧密耦合,这样会降低可重用性。

Observer模式中的关键对象是目标(subject)和观察者(observer.一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得到通知。作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标的状态同步。

这种交互也称为“发布-订阅”。目标是通知的发布者。它发出通知时并不需要知道谁是它的观察者。可以有任意数目的观察者订阅并接收通知。

适用性:

1 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

2 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。

3 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。即不希望对象是紧密耦合的

结构:


 

参与者:

Subject(目标):

1 目标知道它的观察者。可以有任意多个观察者观察同一个目标。

2 提供注册和删除观察者对象的接口。

Observer(观察者):

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

ConcreteSubject(具体目标):

1 将有关状态存入各ConcreteObserver对象。

2 当它的状态发生改变时,向它的各个观察者发出通知。

ConcreteObserver(具体观察者):

1 维护一个指向ConcreteSubject对象的引用

2 存储有关状态,这些状态应与目标的状态保持一致。

3 实现Observer的更新接口以使自身状态与目标的状态保持一致。

协作:

ConcreteSubject发生任何可能导致其观察者与其本身状态不一致的改变时,它将通知它的各个观察者。

在得到一个具体目标的改变通知后,ConcreteObserver对象可向目标对象查询信息。ConcreteObserver使用这些信息以使它的状态与目标对象的状态一致。

如下图说明了一个目标对象和两个观察者之间的协作:

 

发出改变请求的Observer对象并不立即更新,而是将其推迟到它从目标得到一个通知之后。Notify不总是由目标对象调用。也可被一个观察者或其它对象调用。

效果:

1 目标与观察者之间的抽象耦合。

2 支持广播通信:可以广播给所有已向该目标对象登记的有关对象。

3 意外的更新

实现:

1 创建目标到其观察者之间的映射

2 观察多个目标:一个观察者依赖于多个目标。

3 谁触发更新。

A 由目标对象的状态设定操作在改变目标对象的状态后自动调用Notify

B 由客户负责在适当的时候调用Notify

4 对已删除目标的悬挂引用:删除一个目标时不应遗留对该目标的悬挂引用

5 在发出通知前确保目标的状态自身是一致的

6 避免特定于观察者的更新协议----/拉模型

推模型(push model):目标向观察者发生关于改变的详细信息,而不管它们是否需要

拉模型(pull model):目标除最小通知外什么也不送出,这之后由观察者显示向目标询问

7 显示的指定感兴趣的改变

8 封装复杂的更新语义:当目标和观察者间的依赖关系特别复杂时,使用ChangeManager来维护这些关系。目标是尽量减少观察者反应器目标的状态变化所需的工作量。

9 结合目标类和观察者类

相关模式:

Mediator:通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。

SiglentonChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。


代码如下:

//观察者模式 

#include <iostream>
#include <list>
#include <algorithm>
using namespace std;

class Subject;
//抽象观察者 
class Observer
{
public:
	Observer(string name, Subject* sub)
	  : _name(name), _sub(sub)
	{
	}
	  
	virtual void Update() = 0;
protected:
    string _name;
	Subject* _sub; 
};

//通知者接口
class Subject
{
public:
	//增加 
	virtual void Attach(Observer& observer)
	{
		observers.push_back(&observer);
	}
	
	virtual void Detach(Observer& observer)
	{
		observers.remove(&observer);
	}
	
	virtual void Notify()
	{
		//通知每一个观察者 
		for_each(observers.begin(), observers.end(), mem_fun(&Observer::Update));
	}
	
	//状态
	virtual string GetSubjectState()
	{
		return action;
	} 
	
	virtual void SetSubjectState(string value)
	{
		action = value;
	}
protected:
	list<Observer*> observers;
	string action;
}; 

//具体通知者
class Boss : public Subject
{

}; 

//前台秘书类 
class Secretary : public Subject
{
}; 


//看股票的同事
class StockObserver : public Observer
{
public:
	//设置通知者 
	StockObserver(string name, Subject* sub)
	    : Observer(name, sub)
	{
	}
	
	void Update()
	{
		cout << _sub->GetSubjectState() << _name << "关闭股票行情,继续工作" << endl;
	}
}; 

//看NBA的同事
class NBAObserver : public Observer
{
public:
	NBAObserver(string name, Subject* sub)
	    : Observer(name, sub)
	{
	}
	
	void Update()
	{
		cout << _sub->GetSubjectState() << _name << "关闭NBA直播,继续工作!" << endl;
	}
}; 

int main()
{
	//目标,通知者 
	Boss huhansan;
	
	//看股票的同事
	StockObserver tongshi1("魏关宅", &huhansan); 
	//看NBA的同事
	NBAObserver tongshi2("易管查", &huhansan);
	
	huhansan.Attach(tongshi1);
	huhansan.Attach(tongshi2);
	
	//huhansan.Detach(tongshi1);
	
	huhansan.SetSubjectState("我胡汉三回来了!");
	huhansan.Notify();
	
	system("pause");
	return 0; 
	
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值