建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式是一种对象行为型模式。
观察者模式包含如下角色:
#include <iostream>
#include "Subject.h"
#include "Obeserver.h"
#include "ConcreteObeserver.h"
#include "ConcreteSubject.h"
using namespace std;
int main(int argc, char *argv[])
{
Subject * subject = new ConcreteSubject();
Obeserver * objA = new ConcreteObeserver("A");
Obeserver * objB = new ConcreteObeserver("B");
subject->attach(objA);
subject->attach(objB);
subject->setState(1);
subject->notify();
cout << "--------------------" << endl;
subject->detach(objB);
subject->setState(2);
subject->notify();
delete subject;
delete objA;
delete objB;
return 0;
}
///////////////////////////////////////////////////////////
// Subject.h
// Implementation of the Class Subject
// Created on: 07-十月-2014 23:00:10
// Original author: cl
///////////////////////////////////////////////////////////
#if !defined(EA_61998456_1B61_49f4_B3EA_9D28EEBC9649__INCLUDED_)
#define EA_61998456_1B61_49f4_B3EA_9D28EEBC9649__INCLUDED_
#include "Obeserver.h"
#include <vector>
using namespace std;
class Subject
{
public:
Subject();
virtual ~Subject();
Obeserver *m_Obeserver;
void attach(Obeserver * pObeserver);
void detach(Obeserver * pObeserver);
void notify();
virtual int getState() = 0;
virtual void setState(int i)= 0;
private:
vector<Obeserver*> m_vtObj;
};
#endif // !defined(EA_61998456_1B61_49f4_B3EA_9D28EEBC9649__INCLUDED_)
///////////////////////////////////////////////////////////
// Subject.cpp
// Implementation of the Class Subject
// Created on: 07-十月-2014 23:00:10
// Original author: cl
///////////////////////////////////////////////////////////
#include "Subject.h"
Subject::Subject(){
}
Subject::~Subject(){
}
void Subject::attach(Obeserver * pObeserver){
m_vtObj.push_back(pObeserver);
}
void Subject::detach(Obeserver * pObeserver){
for(vector<Obeserver*>::iterator itr = m_vtObj.begin();
itr != m_vtObj.end(); itr++)
{
if(*itr == pObeserver)
{
m_vtObj.erase(itr);
return;
}
}
}
void Subject::notify(){
for(vector<Obeserver*>::iterator itr = m_vtObj.begin();
itr != m_vtObj.end();
itr++)
{
(*itr)->update(this);
}
}
///////////////////////////////////////////////////////////
// Obeserver.h
// Implementation of the Class Obeserver
// Created on: 07-十月-2014 23:00:10
// Original author: cl
///////////////////////////////////////////////////////////
#if !defined(EA_2C7362B2_0B22_4168_8690_F9C7B76C343F__INCLUDED_)
#define EA_2C7362B2_0B22_4168_8690_F9C7B76C343F__INCLUDED_
class Subject;
class Obeserver
{
public:
Obeserver();
virtual ~Obeserver();
virtual void update(Subject * sub) = 0;
};
#endif // !defined(EA_2C7362B2_0B22_4168_8690_F9C7B76C343F__INCLUDED_)
///////////////////////////////////////////////////////////
// ConcreteObeserver.h
// Implementation of the Class ConcreteObeserver
// Created on: 07-十月-2014 23:00:09
// Original author: cl
///////////////////////////////////////////////////////////
#if !defined(EA_7B020534_BFEA_4c9e_8E4C_34DCE001E9B1__INCLUDED_)
#define EA_7B020534_BFEA_4c9e_8E4C_34DCE001E9B1__INCLUDED_
#include "Obeserver.h"
#include <string>
using namespace std;
class ConcreteObeserver : public Obeserver
{
public:
ConcreteObeserver(string name);
virtual ~ConcreteObeserver();
virtual void update(Subject * sub);
private:
string m_objName;
int m_obeserverState;
};
#endif // !defined(EA_7B020534_BFEA_4c9e_8E4C_34DCE001E9B1__INCLUDED_)
///////////////////////////////////////////////////////////
// ConcreteObeserver.cpp
// Implementation of the Class ConcreteObeserver
// Created on: 07-十月-2014 23:00:09
// Original author: cl
///////////////////////////////////////////////////////////
#include "ConcreteObeserver.h"
#include <iostream>
#include <vector>
#include "Subject.h"
using namespace std;
ConcreteObeserver::ConcreteObeserver(string name){
m_objName = name;
}
ConcreteObeserver::~ConcreteObeserver(){
}
void ConcreteObeserver::update(Subject * sub){
m_obeserverState = sub->getState();
cout << "update oberserver[" << m_objName << "] state:" << m_obeserverState << endl;
}
运行结果:
- 作为对这个通知的响应,每个观察者都将即时更新自己的状态,以与目标状态同步,这种交互也称为发布-订阅(publishsubscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通 知。
观察者模式的优点
观察者模式的缺点
在以下情况下可以使用观察者模式:
观察者模式在软件开发中应用非常广泛,如某电子商务网站可以在执行发送操作后给用户多个发送商品打折信息,某团队战斗游戏中某队友牺牲将给所有成员提示等等,凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。
MVC模式