观察者模式又被称为发布订阅模式。它定义了对象之间一对多的依赖,当一个对象状态发生改变时,它的所有依赖者都会收到通知并自动更新相关内容。即建立一个(Subject类)对多(Observer类)的关系,能够使得当Subject的对象变化的时候,依赖这个的多个Observe的对象实例也能够同步进行相应的改变。
优点:
- 观察者和被观察者是抽象耦合的。
- 可以建立一套触发机制。
缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
哪些地方用到了观察者模式?
观察模式应用在一些框架中用的比较多,例如MFC的文档视图就, Qt的事件过滤,信号槽等。
下面是观察者模式的实现代码:
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Observer;
//抽象被观察者
class Subject {
public:
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;
string GetState()
{
return "有新消息发布: " + m_State;
}
void SetState(string state)
{
m_State = state;
}
protected:
std::list<Observer*> m_ObserverList;
string m_State;
};
//抽象观察者
class Observer {
public:
Observer(Subject* sub) :m_Subject(sub) {}
virtual void Update() = 0;
protected:
Subject* m_Subject;
};
//具体观察者1
class Observer1 : public Observer {
public:
Observer1(Subject* p_subject) : Observer(p_subject) {}
void Update() override
{
cout << "Observer1 get the update:" << m_Subject->GetState() << endl;
}
};
//具体观察者2
class Observer2 : public Observer
{
public:
Observer2(Subject* p_subject) : Observer(p_subject) {}
void Update() override
{
cout << "Observer2 get the update:" << m_Subject->GetState() << endl;
}
};
//具体被观察者
class ConcreteSubject : public Subject
{
public:
void Attach(Observer* pObserver) override
{
m_ObserverList.push_back(pObserver);
}
void Detach(Observer* pObserver) override
{
m_ObserverList.remove(pObserver);
}
void Notify() override;
};
//核心操作:循环通知所有观察者
void ConcreteSubject::Notify()
{
auto it = m_ObserverList.begin();
while (it != m_ObserverList.end()) {
(*it++)->Update();
}
}
int main()
{
// 创建被观察者
Subject* p_subject = new ConcreteSubject();
// 创建观察者
Observer* p_observer1 = new Observer1(p_subject);
Observer* p_observer2 = new Observer2(p_subject);
// 改变状态
p_subject->SetState("小米10发布了");
// 注册观察者
p_subject->Attach(p_observer1);
p_subject->Attach(p_observer2);
p_subject->Notify();
// 注销观察值
p_subject->Detach(p_observer1);
p_subject->SetState("华为P40发布了");
p_subject->Notify();
delete p_observer1;
delete p_observer2;
delete p_subject;
return 0;
}
运行结果:
Observer1 get the update:有新消息发布: 小米10发布了
Observer2 get the update:有新消息发布: 小米10发布了
Observer2 get the update:有新消息发布: 华为P40发布了
类图关系:
一个被观察者
多个观察者
来源:oschina
链接:https://my.oschina.net/u/4332520/blog/3233038