在学习《大话设计模式》的时候,将书上C#版本的代码翻译成C++的代码,合上书后,再回想书中的内容和观察者模式,感觉还是不太清楚,我就写博客记录一下,同时也可以梳理自己学到的东西。
书中是这样的构想的场景是这样的:
前台秘书是一个童子喆(zhe)(别读成童子ji了),同时们请她帮忙,老板进门的时候,通知他们一下。
这是一个典型的观察者模式的应用场景,
前台秘书类:
Secretary.h
#pragma once
#include <string>
#include <list>
class StockObserver;
class Secretary
{
public:
Secretary();
~Secretary();
void Attach(StockObserver *observer);
void Detach(StockObserver* observer);
void Notify();
void SetSecretaryAction(const std::string &action);
std::string GetSecretaryAction();
private:
std::string m_action;
std::list<StockObserver*> m_observers;
};
实现文件:
Secretary.cpp
#include "Secretary.h"
#include "StockObserver.h"
Secretary::Secretary()
{
}
Secretary::~Secretary()
{
m_observers.clear();
}
//就是有几个同事请前台帮忙,于是就给集合增加几个对象
void Secretary::Attach(StockObserver * observer)
{
m_observers.push_back(observer);
}
void Secretary::Detach(StockObserver * observer)
{
m_observers.remove_if([observer](StockObserver * eachObserver) {
return observer == eachObserver;
});
}
//通知,待老板来时,就给所有的登记同事发通知,“老板来了”
void Secretary::Notify()
{
for (const auto &observer : m_observers)
{
observer->Update();
}
}
void Secretary::SetSecretaryAction(const std::string & action)
{
m_action = action;
}
std::string Secretary::GetSecretaryAction()
{
return m_action;
}
看股票的同事类:
StockObserver.h
#pragma once
#include <string>
class Secretary;
class StockObserver
{
public:
StockObserver(std::string name, Secretary *sub);
~StockObserver();
void Update();
private:
std::string m_name;
Secretary *m_sub;
};
StockObserver.cpp
#include "StockObserver.h"
#include "Secretary.h"
#include <iostream>
StockObserver::StockObserver(std::string name, Secretary *sub)
:m_name(name)
,m_sub(sub)
{
}
StockObserver::~StockObserver()
{
}
//得到前台通知,赶快采取行动
void StockObserver::Update()
{
std::cout << "{0} {1} 关闭股票行情,继续工作!" << m_sub->GetSecretaryAction().data() << m_name.data() << std::endl;
}
main.cpp
#include "Secretary.h"
#include "StockObserver.h"
int main()
{
//前台小姐童子喆
Secretary *tongzizhe = new Secretary();
//看股票的同事
StockObserver *tongshi1 = new StockObserver("魏关", tongzizhe);
StockObserver *tongshi2 = new StockObserver("易管查", tongzizhe);
tongzizhe->Attach(tongshi1);
tongzizhe->Attach(tongshi2);
tongzizhe->SetSecretaryAction("老板回来了!");
tongzizhe->Notify();
delete tongzizhe;
delete tongshi1;
delete tongshi2;
getchar();
return 0;
}
运行结果:
老板回来了! 魏关关闭股票行情,继续工作!
老板回来了! 易管查关闭股票行情,继续工作!
这样的代码有双向耦合的问题,前台类要增加观察者,观察者需要前台的状态。
比如说前台换成了开门王大爷,那么那些看股票的同事,就需要在Update中获取王大爷的状态。
又比如还有一些上班玩游戏的同事,也需要前台通知,那么前台在Attach函数中增加观察者的时候,也需要改变原来的代码。
(题外话:上班就好好上班,这里是原书作者举的一个例子,用来说明观察者模式的。)
上面的代码就违反了开闭原则,程序应该依赖抽象而不是相互依赖。
书中就继续讲解了如何解耦,我们在下一篇博文中继续。