一、概述
描述:iPhone14通知发布,喜欢的客户都在等着iPhone14售卖,进行购买。此时客户是观察者,iPhone14是被观察者。
观察者不需要时刻盯着被观察者,而是采用注册或者成为订阅的方式告诉被观察者:我需要你的某某状态,你要在它变化时通知我。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。
定义:对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得通知并自动更新。
二、结构
-
抽象主题/抽象被观察者(Subject)角色:将所有观察者对象保存在一个集合中,可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
-
具体主题/具体被观察者(ConcreteSubject)角色:该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
-
抽象观察者(Observer)角色:它定义了一个更新接口,使得在得到主题/被观察者更新时通知自己。
-
具体观察者(ConcrereObserver)角色:实现抽象观察者定义的更新接口,以便在得到主题/被观察者更新时通知自己更新自身状态。
三、实例
#include<iostream>
#include<list>
using namespace std;
//观察者模式
class Observer;
//抽象被观察者
class Subject {
protected:
list<shared_ptr<Observer>> m_pObserver_list;
int m_nState;
public:
Subject() : m_nState(0) {}
virtual ~Subject() = default;
virtual void Attach(const shared_ptr<Observer> pObserver) = 0;
virtual void Detach(const shared_ptr<Observer> pObserver) = 0;
virtual void Notify() = 0;
virtual int GetState() { return m_nState; }
void SetState(int state) {
cout << "Subject updated !" << endl;
m_nState = state;
}
};
//抽象观察者
class Observer {
protected:
shared_ptr<Subject> m_pSubject;
string m_strName;
public:
virtual ~Observer() = default;
Observer(const shared_ptr<Subject> pSubject, const string& name = "unknown")
: m_pSubject(pSubject), m_strName(name) {}
virtual void Update() = 0;
virtual const string& name() { return m_strName; }
};
//具体被观察者
class ConcreteSubject : public Subject {
public:
void Attach(const shared_ptr<Observer> pObserver) override {
auto iter = find(m_pObserver_list.begin(), m_pObserver_list.end(), pObserver);
if (iter == m_pObserver_list.end()) {
cout << "Attach observer" << pObserver->name() << endl;
m_pObserver_list.emplace_back(pObserver);
}
}
void Detach(const shared_ptr<Observer> pObserver) override {
cout << "Detach observer" << pObserver->name() << endl;
m_pObserver_list.remove(pObserver);
}
//循环通知所有观察者
void Notify() override {
auto it = m_pObserver_list.begin();
while (it != m_pObserver_list.end()) {
(*it++)->Update();
}
}
};
//具体观察者1
class Observer1 : public Observer {
public:
Observer1(const shared_ptr<Subject> pSubject, const string& name = "unknown")
: Observer(pSubject, name) {}
void Update() override {
cout << "Observer1_" << m_strName << " get the update.New state is: "
<< m_pSubject->GetState() << endl;
}
};
//具体观察者2
class Observer2 : public Observer {
public:
Observer2(const shared_ptr<Subject> pSubject, const string& name = "unknown")
: Observer(pSubject, name) {}
void Update() override {
cout << "Observer2_" << m_strName << " get the update.New state is: "
<< m_pSubject->GetState() << endl;
}
};
int main() {
shared_ptr<Subject> pSubject = make_shared<ConcreteSubject>();// 创建被观察者
// 创建观察者
shared_ptr<Observer> pObserver1_1 = make_shared<Observer1>(pSubject, "1");
shared_ptr<Observer> pObserver1_2 = make_shared<Observer1>(pSubject, "2");
shared_ptr<Observer> pObserver1_3 = make_shared<Observer1>(pSubject, "3");
shared_ptr<Observer> pObserver2_4 = make_shared<Observer2>(pSubject, "4");
shared_ptr<Observer> pObserver2_5 = make_shared<Observer2>(pSubject, "5");
shared_ptr<Observer> pObserver2_6 = make_shared<Observer2>(pSubject, "6");
// 注册观察者
pSubject->Attach(pObserver1_1);
pSubject->Attach(pObserver1_2);
pSubject->Attach(pObserver1_3);
pSubject->Attach(pObserver2_4);
pSubject->Attach(pObserver2_5);
pSubject->Attach(pObserver2_6);
pSubject->SetState(2);// 改变状态
pSubject->Notify();
cout << std::string(50, '-') << endl;
// 注销观察者
pSubject->Detach(pObserver1_1);
pSubject->Detach(pObserver1_2);
pSubject->SetState(3);
pSubject->Notify();
return 0;
}
四、优缺点
优点:
-
开闭原则。 你无需修改发布者代码就能引入新的订阅者类(如果是发布者接口则可轻松引入发布者类)。
-
可以在运行时建立对象之间的联系。
-
观察者和被观察者是抽象耦合的。
缺点:
-
若一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
-
若观察者和观察目标间有循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
-
.观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
五、适用场景
-
当一个对象状态的改变需要改变其他对象,或实际对象是事先未知的或动态变化的时,可使用观察者模式。
-
跨系统的消息变换场景,如消息队列的处理机制
-
个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用
六、对比
观察者模式和中介模式:
-
.都属于行为型模式。
-
都为了处理一对多的关系。
-
.UML实现基本相同,都有集合管理业务对象的集。