目录导读
目录
观察者模式 简介
当对象存在一对多的关系时,则使用观察者模式(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;
}