观察者模式概念
C++观察者模式(Observer Pattern)是一种设计模式,它用于在对象之间建立一种一对多的依赖关系。在该模式中,当一个对象(称为主题)发生变化时,所有依赖于它的对象(称为观察者)都会得到通知并自动更新。
观察者模式通常包含以下几个角色:
主题(Subject):也称为被观察者或可观察对象,它维护一个观察者列表并提供添加、删除和通知观察者的方法。
观察者(Observer):定义一个更新接口,使得在主题状态改变时能够得到通知。
具体主题(ConcreteSubject):实现主题接口,具体主题对象在状态变化时通知观察者。
具体观察者(ConcreteObserver):实现观察者接口,具体观察者对象在接收到通知后进行相应的更新操作。
在C++中实现观察者模式可以使用以下步骤:
(1)定义主题接口 Subject,包括添加观察者、删除观察者和通知观察者的方法。
(2)定义观察者接口 Observer,包括更新方法。
(3)实现具体主题类 ConcreteSubject,维护观察者列表,实现添加观察者、删除观察者和通知观察者的方法。
(4)实现具体观察者类 ConcreteObserver,实现更新方法。
(5)在使用时,创建具体主题对象和具体观察者对象,并将观察者注册到主题中。
当具体主题对象的状态发生变化时,他会变量观察者列表,调用观察者的更新方法,从而实现观察者模式的效果。这样观察者就能根据主题的状态进行相应的操作,实现对象之间的松耦合关系。
观察者也叫订阅者,主题也叫发布者,谁发布,谁订阅,发布者维护一个订阅者列表,想订阅的人被添加到该列表中,每当要发布消息时,发布者就会轮询这个列表,订阅者就会收到消息。
实例代码
#include<iostream>
#include<vector>
using namespace std;
//抽象观察者接口
class Observer
{
public:
virtual void recive(int data) = 0; //订阅者的接受方法,用来接受发布者消息
};
//具体订阅者A
class ConcreteObserverA : public Observer
{
public:
void recive(int data) override
{
cout << "i am A,i accept data:" << data << endl;
}
};
//具体订阅者A
class ConcreteObserverB : public Observer
{
public:
void recive(int data) override
{
cout << "i am B,i accept data:" << data << endl;
}
};
//抽象发布者
class Subscribe
{
public:
virtual void attach(Observer* observer) = 0; //添加观察者,将观察者添加到列表中,纯虚函数
virtual void detach(Observer* observer) = 0; //删除观察者,将观察者从列表中删除,纯虚函数
virtual void notify(int data) = 0; //通知观察者
};
//具体发布者
class SubscribeS : public Subscribe
{
private:
vector<Observer*> observers; //存储观察者列表
public:
void attach(Observer* observer) override//添加观察者,将观察者添加到列表中,纯虚函数
{
observers.push_back(observer);
}
void detach(Observer* observer) //删除观察者,将观察者从列表中删除,纯虚函数
{
for (auto &it : observers)
{
auto it = std::find(observers.begin(), observers.end(), observer);
if (it != observers.end())
{
observers.erase(it);
}
}
}
void notify(int data) //通知观察者
{
for (auto& it : observers)
{
it->recive(data);
}
}
};
int main()
{
SubscribeS s;
ConcreteObserverA a;
ConcreteObserverB b;
s.attach(&a);
s.attach(&b);
s.notify(123456);
s.detach(&b);
s.notify(33333333333333333);
return 0;
}