一、概述
1、观察着模式:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并自动更新。
2、发生改变的对象称为观察目标,被通知的对象称为观察者
3、一个观察目标可以对应多个观察者
4、别名:发布-订阅模式、模型-视图模式、源-监听器模式、从属者模式
二、观察者模式的结构
观察者模式包含以个下4个角色:
Subject(主题):主题是一个包含观察者列表的抽象类或接口,它提供注册、删除、通知观察者的方法。当主题发生变化时,它会调用通知方法来更新所有注册的观察者
ConcreteSubject(具体主题):具体主题实现主题的接口,通常包含具体的状态或数据。当这些数据发生变化时,它会通知所有的观察者
Observer(观察者):观察者是一个抽象类或接口,定义了观察者接收到通知需要执行的操作
ConcreteObserver(具体观察者):具体观察者实现观察者的接口,并在接受到通知时执行具体操作
三、UML图
四、观察者模式的实现步骤
1、创建一个观察者接口(Observe)
class Observe
{
public:
virtual ~Observe() = default;
virtual void update(const string& message) = 0;
};
2、实现具体的观察者(ConcreteObserver)
class LOLObserve : public Observe
{
public:
void update(const string &message) override
{
if (message == "夏季赛开播了")
cout << "我准备要开始看游戏比赛了" << endl;
}
};
class NBAObserve : public Observe
{
public:
void update(const string& message)
{
if (message == "NBA比赛开始了")
cout << "收到,准备进场";
}
};
3、定义主题接口(Subject)
class Subject
{
public:
virtual ~Subject() = default;
virtual void addMember(std::shared_ptr<Observe> observe) = 0;
virtual void removeMember(std::shared_ptr<Observe> observe) = 0;
virtual void notify(const string &message) const = 0;
protected:
vector<std::shared_ptr<Observe>> m_children;
};
4、实现具体主题(ConcreteSubject)
class ConcreteSubject : public Subject
{
public:
void addMember(std::shared_ptr<Observe> observe) override
{
m_children.push_back(std::move(observe));
}
void removeMember(std::shared_ptr<Observe> observe) override
{
auto it = m_children.begin();
while (it != m_children.end())
{
if (*it == observe)
{
m_children.erase(it);
break;
}
++it;
}
}
void notify(const string& message) const override
{
for (auto observe : m_children)
observe->update(message);
}
};
5、客户端使用
int main()
{
std::shared_ptr<Observe> lolObserve = std::make_shared<LOLObserve>();
std::shared_ptr<Observe> nbaObserve = std::make_shared<NBAObserve>();
std::shared_ptr<Subject> subject = std::make_shared<ConcreteSubject>();
subject->addMember(lolObserve);
subject->addMember(nbaObserve);
string message = "NBA比赛开始了";
cout << message << endl;
subject->notify("NBA比赛开始了");
return 0;
}
6、输出结果
NBA比赛开始了
收到,准备进场
五、观察者模式适用的场景
1、事件驱动系统:当一个对象的状态变化时,需要通知其他依赖于该对象的多个对象,比如图形用户界面(GUI)系统中的按钮点击事件
2、数据变化通知:在数据模型与视图之间,视图需要根据数据的变化进行更新。比如在 MVC(模型-视图-控制器)架构中,模型的变化会通知视图进行更新。
3、发布-订阅系统:当一个对象(发布者)有多个对象(订阅者)需要接收消息或更新时,例如消息队列、通知系统等。
4、依赖关系动态管理:当一个对象的状态变化会影响到其他多个对象,而这些对象的数量和类型在运行时可能会变化。观察者模式可以动态地增加或删除观察者。
5、跨组件通信:在一些大型系统中,组件之间的耦合度需要最小化。观察者模式可以实现不同组件之间的低耦合通信。
六、模式优点
1、可以实现表示层和数据逻辑层的分离
2、在观察目标和观察者之间建立一个抽象的耦合
3、支持广播通信,简化了一对多系统设计的难度
4、符合开闭原则,增加新的具体观察者无需修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便
七、模式缺点
1、将所有观察者都通知到会花费很多时间
2、如果存在循环依赖时可能导致系统崩溃
3、没有相应的机制让观察者知道所观察的目标对象是怎样变化的,而只是知道观察目标发生了变化