建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式是一种对象行为型模式。
观察者模式包含如下角色:
— 目标知道它的观察者。可以有任意多个观察者观察同一个目标。
— 提供注册和删除观察者对象的接口。
— 将有关状态存入各ConcreteObserver对象。
— 当它的状态发生改变时, 向它的各个观察者发出通知。
— 为那些在目标发生改变时需获得通知的对象定义一个更新接口。
— 维护一个指向ConcreteSubject对象的引用。
— 存储有关状态,这些状态应与目标的状态保持一致。
— 实现Observer的更新接口以使自身状态与目标的状态保持一致。
observer.h
/*************************************************
// Copyright (C), 2012-2019, CS&S. Co., Ltd.
// File name: observer.h
// Author: pengsh
// Version: 1.0
// Date: 2019/07/28
// Description: 抽象观察者类,为所有的具体观察者定义了统一的更新接口,得到主题的通知时更新自己
// Others:
// History:
// pengsh
//
Observer.cpp
#include "Observer.h"
Observer::Observer()
{
}
Observer::~Observer()
{
}
ConcreteObserver.h
/*************************************************
// Copyright (C), 2012-2019, CS&S. Co., Ltd.
// File name: ConcreteObserver.h
// Author: pengsh
// Version: 1.0
// Date: 2019/07/29
// Description: ConcreteObserver为具体的观察者,实现了抽象观察者所要求的更新接口,以便使本身的状态与主题的状态相协调
— 维护一个指向ConcreteSubject对象的引用。
— 存储有关状态,这些状态应与目标的状态保持一致。
— 实现Observer的更新接口以使自身状态与目标的状态保持一致。
// Others:
// History:
// pengsh
//
ConcreteObserver.cpp
#include "ConcreteObserver.h"
#include
ConcreteObserver::ConcreteObserver(string name)
{
m_objName = name;
}
ConcreteObserver::~ConcreteObserver()
{
}
void ConcreteObserver::Update(Subject * sub)
{
if (NULL == sub)
return;
m_observerState = sub->GetState();
cout << "update oberserver[" << m_objName << "] state:" << m_observerState << endl;
}
Subject.h
/*************************************************
// Copyright (C), 2012-2019, CS&S. Co., Ltd.
// File name: Subject.h
// Author: pengsh
// Version: 1.0
// Date: 2019/07/29
// Description: Subject(主题或目标) 可以有任意多个观察者观察同一个目标。提供注册和删除观察者对象的接口。
// Others:
// History:
// pengsh
//
Subject.cpp
#include "Subject.h"
#include "Observer.h"
Subject::Subject()
{
}
Subject::~Subject()
{
}
void Subject::Attach(Observer *pObserver)
{
m_ListObserver.push_back(pObserver);
}
void Subject::Detach(Observer *pObserver)
{
std::list::iterator it;
for (it = m_ListObserver.begin(); it != m_ListObserver.end(); )
{
if (*it == pObserver)
{
m_ListObserver.erase(it++); //移除元素的时候,it++防止迭代器失效,引起崩溃
//return; 删除单个元素,直接退出也可以
}
else
{
it++;
}
}
}
void Subject::Notify()
{
std::list::iterator it;
for (it = m_ListObserver.begin(); it != m_ListObserver.end(); it++)
{
(*it)->Update(this);
}
}
ConcreteSubject.h
/*************************************************
// Copyright (C), 2012-2019, CS&S. Co., Ltd.
// File name: ConcreteSubject.h
// Author: pengsh
// Version: 1.0
// Date: 2019/07/29
// Description: 将有关状态存入各ConcreteObserver对象。 当它的状态发生改变时, 向它的各个观察者发出通知
// Others:
// History:
// pengsh
//
ConcreteSubject.cpp
#include "ConcreteSubject.h"
ConcreteSubject::ConcreteSubject()
{
}
ConcreteSubject::~ConcreteSubject()
{
}
void ConcreteSubject::SetState(STATE nState)
{
m_nSubjectState = nState;
}
STATE ConcreteSubject::GetState()
{
return m_nSubjectState;
}
main.cpp
#include
#include "Subject.h"
#include "observer.h"
#include "ConcreteObserver.h"
#include "ConcreteSubject.h"
using namespace std;
int main(int argc, char *argv[])
{
Subject * subject = new ConcreteSubject();
Observer * objA = new ConcreteObserver("A");
Observer * objB = new ConcreteObserver("B");
Observer * objC = new ConcreteObserver("C");
subject->Attach(objA);
subject->Attach(objB);
subject->Attach(objC);
subject->SetState(1);
subject->Notify();
cout << "--------------------" << endl;
subject->Detach(objC);
subject->Detach(objB);
subject->SetState(2);
subject->Notify();
delete subject;
delete objA;
delete objB;
delete objC;
getchar();
}
运行结果:
update oberserver[A] state:1
update oberserver[B] state:1
update oberserver[C] state:1
--------------------
update oberserver[A] state:2
知。
观察者模式的优点
观察者模式的缺点
在以下情况下可以使用观察者模式:
观察者模式在软件开发中应用非常广泛,如某电子商务网站可以在执行发送操作后给用户多个发送商品打折信息,某团队战斗游戏中某队友牺牲将给所有成员提示等等,凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。
MVC模式
源码地址:
[email protected]:Varygod/CPP_Study.git
参考:参考资料