让我们来看看《大话设计模式》这本书中对于观察者模式的定义:其又叫发布—订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当这个主题对象在状态发生变化时,会通知所有的观察者对象,是他们可以随之自动更新自己的状态。
其组成大概分为至少4个部分:观察者接口、发布者接口、一般是1个发布者、不止一个的观察者
将一个系统分割成一系列相互协作的类,同时又需要维护类间的一致性,观察者模式可以避免各类紧密耦合。
当一个对象的改变需要同时改变其他对象,且它可能不知道具体有多少对象有待改变时,应该考虑使用观察者模式。
其目的就是解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而保证各自的变化都不会影响另一边,只有在特定的状态发生更新时,才会通知到另一方。
C++实现案例:
1、首先是简单的《大话设计模式》当中提及的案例:办公室员工A、B、C在看股票看电影,这时老板回来了,被A、B、C重金贿赂后的前台发出通知给A、B、C,A、B、C收到通知后赶紧关电脑,关股票窗口,装作在干活。
首先是观察者接口,它需要定义出更新的虚函数给具体观察者继承
class IObserver { public: virtual ~IObserver() {}; virtual void updata(string strEvent) = 0; };
其次是发布者接口,它需要定义出的虚函数包括:添加观察者、删除观察者、更新状态信息
class ISubject { public: virtual void addObserver(IObserver *ob) = 0; virtual void delObserver(IObserver *ob) = 0; virtual int notify(string strEvent) = 0; };
之后是具体的发布者,对接口中的虚函数进行重写
class CBoss: public ISubject { public: virtual void addObserver(IObserver *ob) { m_listObserver.push_back(ob); } virtual void delObserver(IObserver *ob) { m_listObserver.remove(ob); } virtual int notify(string strEvent) { if (!m_listObserver.empty()) { list<IObserver*>::iterator itObserver; for (itObserver = m_listObserver.begin(); itObserver != m_listObserver.end(); ++itObserver) { IObserver* pObserver = *itObserver; pObserver->updata(strEvent); } } return m_listObserver.size(); } void Come() { cout << "Boss : hello boys ,I come in" << endl; notify("Boss come"); } void Leave() { cout << "Boss : Good bye boys" << endl; notify("Boss leave"); } private: list<IObserver*> m_listObserver; };
然后是写具体观察者,对更新虚函数进行重写
class CObserver:public IObserver { public: CObserver(string NameObserver) : m_NameObserver(NameObserver) {}; virtual void updata(string strEvent) { cout << m_NameObserver + " get " + strEvent + " call!!" << endl; } private: string m_NameObserver; };
最后是对于它们的使用,定义出多个观察者对象和具体发布者,在实际使用中可以是多个具体观察者类的多个对象,随后由具体发布者将观察者对象添加到观察者列表中,当特定的状态发生改变时,观察者的状态将随之改变。
int main() { CObserver CObserver1("jams"), CObserver2("kobe"); CBoss oCBoss; oCBoss.addObserver(&CObserver1); oCBoss.addObserver(&CObserver2); oCBoss.Come(); oCBoss.delObserver(&CObserver2); oCBoss.Leave(); system("pause"); return 0; }
运行效果:
2、第二个案例是引用该博客(https://blog.csdn.net/SuperYang_/article/details/79041345)中的气象站的例子,我认为也很好,和上述案例有所不同的是,该案例中对于观察者列表中观察者的添加和删除是写在具体观察者类内部的,我认为这将不利于代码的扩展和维护。但整体思路是值得借鉴和学习的。
OK,这就是观察者模式的基本内容了,之后会陆续开始将前期学习的其他设计模式进行更新记录,希望之后可以重新回到学习刷题的轨道