一、观察者模式
观察者模式又叫做发布-订阅(Public/Subscribe)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
观察者模式(Observer)结构图:
动机:
将一个系统分割成一系列相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维护一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。
观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生改变,所有的Observer都可以得到通知。Subject发出通知时并不需要知道谁是它的观察者,也就是说,具体观察者是谁,它根据不需要了解。而任何一个具体的观察者不知道也不需要知道其他观察者的存在。
总的来说,观察者模式就是解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
二、实现
抽象观察者:
#pragma once
class Observer
{
public:
virtual void Update() = 0;
};
Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现。更新接口通常包含一个Update()方法,这个方法叫做更新方法。
抽象通知者:
#pragma once
#include "Observer.h"
class Subject
{
public:
virtual void Attach(Observer *) = 0; // 添加观察者
virtual void Detach(Observer *) = 0; // 移除观察者
virtual void Notify() = 0; // 通知观察者
};
Subject类,可翻译为主题或者抽象通知者,一般用一个抽象类或者一个接口实现。它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
具体观察者:
#pragma once
#include<iostream>
#include<string>
#include"Observer.h"
using namespace std;
class StockObserver : public Observer
{
public:
void Update() override {
std::cout << " 关闭股票软件,继续工作。 " << std::endl;
}
};
StockObserver,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体的子类实现。
具体通知者:
#pragma once
#include<list>
#include"Observer.h"
#include"Subject.h"
class Secretary : public Subject
{
public:
void Attach(Observer* pObserver)override{
list_observer_.push_back(pObserver);
}
void Detach(Observer* pObserver)override {
list_observer_.remove(pObserver);
}
void Notify() override {
for (auto t : list_observer_)
{
t->Update();
}
}
private:
std::list<Observer*> list_observer_;
};
Secretary,具体的主题或者具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
main.cpp实现:
#include<iostream>
#include<string>
#include "Secretary.h"
#include "StockObserver.h"
using namespace std;
int main()
{
// 通知者实体 秘书
Secretary* secretary = new Secretary();
// 看股票的同事
StockObserver* stock_observer = new StockObserver();
secretary->Attach(stock_observer);
secretary->Notify();
delete secretary;
delete stock_observer;
system("pause");
return 0;
}