1. 意图
定义对象间的一种一对多的依赖关系,
当一个对象的状态改变时,所有依赖于它的对象都得到通知并被自动更新。
2. 四种角色
抽象目标(Subject)、具体目标(Concrete Subject)、抽象观察者(Observer)、
具体观察者(Concrete Observer)
3. 优点
3.1 目标和观察者之间的耦合是抽象的。
3.2 支持广播通信。
4. 缺点
4.1 可能导致意外的更新。
5. 相关模式
当目标和观察者间的依赖关系特别复杂时,需要一个维护这些关系的对象,
这样的对象称为ChangeMananger。
5.1 ChangeManager可使用单例模式来保证它是唯一的并且是可全局访问的。
5.2 ChangeManager充当目标和观察者之间的Mediator
6. 代码示意(C++)
#pragma once
#include <string>
#include <iostream>
#include <vector>
using namespace std;
class Subject;
class Observer
{
public:
virtual void Update(Subject* pSubject) = 0;
protected:
Observer() {}
};
class ConcreteObserver :public Observer
{
string m_state;
string m_name;
public:
ConcreteObserver(const string& name) :m_name(name) {
}
virtual void Update(Subject* pSubject);
};
class Subject
{
vector<Observer*> m_observers;
public:
virtual string GetState() = 0;
virtual void SetState(const string& state) = 0;
public:
void Attach(Observer* pObserver) {
m_observers.emplace_back(pObserver);
cout << "After attached, observers size is:" << m_observers.size() << endl;
}
void Detach(Observer* pObserver) {
m_observers.erase(std::remove_if(m_observers.begin(), m_observers.end(), [&](Observer* p) { return p == pObserver; }), m_observers.end());
cout << "After detached, observers size is:" << m_observers.size() << endl;
}
void Notify()
{
auto it = m_observers.begin();
while (it != m_observers.end()) {
(*it)->Update(this);
++it;
}
}
protected:
Subject(){}
};
class ConcreteSubject :public Subject
{
string m_state;
public:
virtual string GetState() {
return m_state;
}
virtual void SetState(const string& state) {
m_state = state;
}
};
Observer.cpp:
#include "Observer.h"
void ConcreteObserver::Update(Subject* pSubject) {
m_state = pSubject->GetState();
cout << "Observer:" << m_name << ",got state from subject:" << m_state << endl;
}
#include "Observer.h"
int main() {
Subject* pSubject = new ConcreteSubject();
Observer* pObserver1 = new ConcreteObserver("obs1");
Observer* pObserver2 = new ConcreteObserver("obs2");
pSubject->Attach(pObserver1);
pSubject->Attach(pObserver2);
pSubject->SetState("hello1");
pSubject->Notify();
pSubject->Detach(pObserver1);
pSubject->SetState("hello2");
pSubject->Notify();
delete pObserver2;
delete pObserver1;
delete pSubject;
return 0;
}
运行结果:
6.1 目标和观察者之间只知道彼此的抽象类(3.1)。
6.2 Subject::Notify里的循环就是广播,观察者自己决定是否处理某一通知(3.2)。
6.3 使用ChangeMananger会使代码复杂些,但简化了Subject,且使更新策略更加灵活。
使用ChangeMananger代码示意:
#pragma once
#include <string>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
class Subject;
class Observer
{
public:
virtual void Update(Subject* pSubject) = 0;
virtual string GetName() = 0;
protected:
Observer() {}
};
class ConcreteObserver :public Observer
{
string m_state;
string m_name;
public:
ConcreteObserver(const string& name) :m_name(name) {
}
virtual string GetName() { return m_name; }
virtual void Update(Subject* pSubject);
};
class ChangeManager;
class SimpleChangeManager;
class Subject
{
ChangeManager* m_pChangeManager;
public:
virtual string GetState() = 0;
virtual void SetState(const string& state) = 0;
virtual ~Subject();
public:
void Attach(Observer* pObserver);
void Detach(Observer* pObserver);
void Notify();
protected:
Subject();
};
class ConcreteSubject :public Subject
{
string m_state;
public:
ConcreteSubject() {
}
virtual string GetState() {
return m_state;
}
virtual void SetState(const string& state) {
m_state = state;
}
};
class ChangeManager
{
public:
virtual void Register(Subject* pSubject, Observer* pObserver) = 0;
virtual void Unregister(Subject* pSubject, Observer* pObserver) = 0;
virtual void Notify() = 0;
protected:
ChangeManager() {}
};
class SimpleChangeManager :public ChangeManager
{
map<Subject*, vector<Observer*> > m_mapSubjects;
private:
static SimpleChangeManager* s_instance;
public:
static ChangeManager* Instance() {
if (0 == s_instance) {
s_instance = new SimpleChangeManager();
}
return s_instance;
}
public:
virtual void Register(Subject* pSubject, Observer* pObserver) {
vector<Observer*>& observers = m_mapSubjects[pSubject];
auto it = find(observers.begin(), observers.end(), pObserver);
if (it == observers.end()) {
observers.emplace_back(pObserver);
cout << pObserver->GetName() << " is registered successful" << endl;
}
else {
cout << pObserver->GetName() << " is already registered" << endl;
}
}
virtual void Unregister(Subject* pSubject, Observer* pObserver) {
auto it = m_mapSubjects.find(pSubject);
if (it == m_mapSubjects.end()) {
cout << "No need unregister in map for:" << pObserver->GetName() << endl;
}
else {
vector<Observer*>& observers = m_mapSubjects[pSubject];
auto itRemove = remove_if(observers.begin(), observers.end(), [&](Observer* p) { return p == pObserver; });
if (itRemove == observers.end()) {
cout << "No need unregister in vector for:" << pObserver->GetName() << endl;
}
else {
observers.erase(itRemove, observers.end());
cout << pObserver->GetName() << " is unregistered successful" << endl;
if (observers.size() == 0) {
m_mapSubjects.erase(pSubject);
}
}
}
}
virtual void Notify() {
for (auto& pair : m_mapSubjects) {
vector<Observer*>& observers = pair.second;
auto it = observers.begin();
while (it != observers.end()) {
(*it)->Update(pair.first);
++it;
}
}
}
protected:
SimpleChangeManager() {}
};
Observer.cpp:
#include "Observer.h"
void ConcreteObserver::Update(Subject* pSubject) {
m_state = pSubject->GetState();
cout << "Observer:" << m_name << ",got state from subject:" << m_state << endl;
}
Subject::Subject() {
m_pChangeManager = SimpleChangeManager::Instance();
}
Subject::~Subject() {
delete m_pChangeManager;
}
void Subject::Attach(Observer* pObserver) {
m_pChangeManager->Register(this, pObserver);
}
void Subject::Detach(Observer* pObserver) {
m_pChangeManager->Unregister(this, pObserver);
}
void Subject::Notify()
{
m_pChangeManager->Notify();
}
SimpleChangeManager* SimpleChangeManager::s_instance = 0;
#include "Observer.h"
int main() {
Subject* pSubject = new ConcreteSubject();
Observer* pObserver1 = new ConcreteObserver("obs1");
Observer* pObserver2 = new ConcreteObserver("obs2");
pSubject->Attach(pObserver1);
pSubject->Attach(pObserver2);
pSubject->Attach(pObserver1);
pSubject->SetState("hello1");
pSubject->Notify();
pSubject->Detach(pObserver1);
pSubject->Detach(pObserver1);
pSubject->SetState("hello2");
pSubject->Notify();
pSubject->Detach(pObserver2);
pSubject->Detach(pObserver2);
delete pObserver2;
delete pObserver1;
delete pSubject;
return 0;
}
运行结果: