设计模式(3)---观察者模式

观察者模式

当对象存在一对多的关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它依赖对象。观察者模式属于行为型模式,又被称为发布-订阅模式、模式-视图模式、源-监听器模式或从属者模式。观察者模式中分为目标和观察者,目标可以被多个观察者所观察,目标的状态变化发生变化时,观察该目标的所有观察者将得到通知,通常被用作事件的实时处理。这种模式类似于电影上摇骰子的情况,这时那些赌徒就是观察者,那个骰子就是目标,当骰盅被打开时会有一个人来读点,用来通知给那些下注的赌徒,那些赌徒会根据骰子的点数作出相应的动作。

适用情景:

(1)C/S模式下的消息实时发布。

(2)股票大盘的消息实时更新。

模式结构

观察者模式中具体分为:

(1)目标(subject):目标将所有观察者对象保存在一个聚集(数组、链表)里,每个目标都可以拥有任意数量的观察者。目标提供一个接口,可以增加和删除观察者的对象,目标又被称为:抽象主题角色或被观察者角色,一般使用一个抽象类或接口实现。

 (2)具体目标 (Concrete Subject):将有关状态状态存入具体观察者对象;当具体目标的内部状态改变时,给登记过的观察者(观察该目标的所有观察者)发出通知。具体目标又被称为:具体主题角色或具体被观察者角色,一般使用一个具体的子类实现。

(3) 观察者 (observer):为所有的具体观察者定义一个接口,在得到目标的通知时更新自己。这个接口叫做更新接口。观察者一般用一个抽象类或者一个接口实现。在抽像类中,更新接口只包含一个方法(updata方法),这个方法叫做更新方法。观察者又被称为抽象观察者角色。

 (4)具体观察者(Concrete Observer):存储与目标的状态自恰的状态。具体观察者实现了观察者的所有更新接口,以便使本身的状态与目标状态协调。如果需要,具体观察者角色可以保存一个指向具体目标对象的引用或指针。具体观察者又被称为具体观察者角色,通常使用一个具体的子类实现。

其中,目标和观察者属于抽像类为具体目标和具体观察者提供接口。

观察者模式的优点:

(1)观察者模式在目标和观察者之间建立了一个抽象的耦合。被观察者角色所知道的只是一个具体的观察者的聚集,每一个具体的观察者都符合一个抽象观察者的接口。目标并不认识任何一个具体的观察者,它只知道它们都有一个共同的接口。由于目标和观察者没有紧密的耦合在一起,因此它们可以属于不同的抽象化层次。

(2)观察者模式支持广播通信。目标会向所有的登记过的观察者发出通知。

观察者模式的缺点:

(1)如果一个目标有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。

(2)如果在目标和观察者之间有循环依赖的化,目标会触发它们的循环调用,导致程序崩溃。

(3)观察无法知道目标时如何变化的,只能被动的接受变化的结果。

具体实现

#include <iostream>
#include <string>
#include <list>
using namespace std;
//观察者
class Observer
{
public:
	Observer()
	{

	}
	virtual ~Observer()
	{

	}
	//负责更新目标的通知
	virtual void updata() = 0;
};
//目标
class Subject
{
public:
	Subject()
	{

	}
	virtual ~Subject()
	{

	}
	void addObserver(Observer* pObject); //添加观察者
	void delObserver(Observer* pObject); //删除观察者
	void noticeAllObserver();            //通知观察者
	virtual int getStatus() = 0;         //获取目标状态
	virtual void setStatus(int) = 0;     //设置目标状态
private: 
	list<Observer*> observerList;         //用来保存观察者的队列
};

void Subject::addObserver(Observer* pObject)
{
	observerList.push_back(pObject);
}

void Subject::delObserver(Observer* pObject)
{
	list<Observer*>::iterator iter = observerList.begin();
	for (; iter != observerList.end(); ++iter)
	{
		if (*iter == pObject)
		{
			iter = observerList.erase(iter);
			break;
		}
	}
}

void Subject::noticeAllObserver()
{
	list<Observer*>::iterator iter = observerList.begin();
	for (; iter != observerList.end(); ++iter)
	{
		(*iter)->updata();
	}
}
//实际观察者
class concreteObserver :public Observer
{
public:
	concreteObserver(string obName, Subject* subject)
		:observerName(obName), mySubject(subject)
	{

	}
	~concreteObserver()
	{

	}
	void updata()
	{
		cout << "updata:[myName:" << observerName << ",mySubjectStatus:" << mySubject->getStatus() << "]" << endl;
	}
private:
	string observerName;   //观察者名称
	Subject* mySubject;    //观察者观察的目标
};
//实际目标
class concreteSubject:public Subject
{
public:
	concreteSubject(string subName,int status)
		:subjectName(subName), subjectStatus(status)
	{
		cout << "subjectName:" << subjectName << ",subjectStatus:" << subjectStatus << endl;
	}
	int getStatus()
	{
		return subjectStatus;
	}
	void setStatus(int status)
	{
		subjectStatus = status;
		cout << "subjectName:" << subjectName << ",subjectStatus:" << subjectStatus << endl;
	}
private:
	string subjectName;   //目标名称
	int subjectStatus;    //目标状态
};

int main()
{
	concreteSubject *subjectA = new concreteSubject("目标A",1);
	concreteSubject *subjectB = new concreteSubject("目标B",2);
	concreteObserver *observer1 = new concreteObserver("1号观察者", subjectA);
	subjectA->addObserver(observer1);
	concreteObserver *observer2 = new concreteObserver("2号观察者", subjectA);
	subjectA->addObserver(observer2);
	concreteObserver *observer3 = new concreteObserver("3号观察者", subjectB);
	subjectB->addObserver(observer3);
	concreteObserver *observer4 = new concreteObserver("4号观察者", subjectB);
	subjectB->addObserver(observer4);
	subjectA->noticeAllObserver();
	subjectB->noticeAllObserver();
	//目标A,状态 1:1号观察者,2号观察者
	//目标B,状态 2:3号观察者,4号观察者
	cout << "-------------------修改目标A和目标B的状态--------------------------" << endl;
	subjectA->setStatus(3);
	subjectB->setStatus(4);
	subjectA->noticeAllObserver();
	subjectB->noticeAllObserver();
	//目标A,状态 3:1号观察者,2号观察者
	//目标B,状态 4:3号观察者,4号观察者
	cout << "-------------------让1、3观察A,让2、4观察B--------------------------" << endl;
	subjectA->delObserver(observer2);
	subjectB->delObserver(observer3);
	subjectA->addObserver(observer3);
	subjectB->addObserver(observer2);
	subjectA->setStatus(5);
	subjectB->setStatus(6);
	subjectA->noticeAllObserver();
	subjectB->noticeAllObserver();
	//目标A,状态 5:1号观察者,3号观察者
	//目标B,状态 6:2号观察者,4号观察者
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值