设计模式之观察者模式
观察者模式的目的
定义了一种对象间一对多的依赖关系,当被观察者状态发生变化时,所有依赖于被观察者得到通知并改变自身状态
观察者模式也称为发布-订阅模式,现实中这种场景使用的相当的普遍,比如我们关注了一些大V博客、微博之类的,当这些大V发布一些消息,系统会自动的推送给这些订阅者。
观察者模式描述这种如何建立这种关系,其中关键对象是目标和观察者一个目标可以有多个观察者(一个观察者也可以有多个目标这里暂不讨论),一旦目标发生状态变化,就通知所有的观察者,观察者则更新自身状态与目标状态保持一致。
使用场景
1.当一个抽象模型有两个方面,其中一方面一另一面,将这二者封装在独立的对象中以使它们可以各自独立的改变和复用。
2.当一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
3.当一个对象必须通知其他对象,而他又不能假定其他对象是谁。换而言之,不希望这些对象是紧密耦合的。
示例代码
话说千遍不如码撸一遍,请看王大锤与李大嘴的股海沉浮路:
头文件: Observer.h
#pragma once
#include <iostream>
#include <cstdint>
#include <list>
#include <string>
class StockMarket {
public:
StockMarket() :MarketVal(0) {}
~StockMarket() {}
void SetVal(uint32_t v)
{
MarketVal = v;
}
uint32_t GetVal() const
{
return MarketVal;
}
private:
uint32_t MarketVal;
};
class Chives {
public:
Chives() {}
virtual ~Chives() {}
virtual void Update() = 0;
};
class Spokesperson {
public:
virtual ~Spokesperson() {}
virtual void Attach(Chives *ob)
{
Obs.push_back(ob);
}
virtual void Dettach(Chives *ob)
{
Obs.remove(ob);
}
virtual void Notify()
{
for (auto &it : Obs) {
it->Update();
}
}
protected:
Spokesperson() {} //禁止实例化
private:
std::list<Chives*> Obs;
};
class LiDaXiao : public Spokesperson{
public:
LiDaXiao(const std::string nm) : name(nm) {}
~LiDaXiao()
{
std::cout<< name << ": 大西洋底, 太平洋底, ..底, 老铁别慌,还有几个底.." << std::endl;
}
void PullCalf(uint32_t v)
{
SMarket.SetVal(v);
std::string state;
if (v > 3000) {
state = ": 青春底";
} else if (v > 2500) {
state = ": 少女底";
} else if (v > 2000) {
state = ": 婴儿底";
} else {
state = ": 棺材底";
}
std::cout << name << state << std::endl;
Notify();
}
StockMarket SMarket;
private:
std::string name;
};
class WangDaChui : public Chives {
public:
WangDaChui(const std::string nm, LiDaXiao* obj) : name(nm), ObjState(obj)
{
ObjState->Attach(this);
}
~WangDaChui()
{
ObjState->Dettach(this);
}
void Update()
{
uint32_t v = ObjState->SMarket.GetVal();
std::string state;
if (v > 3000) {
state = ": 老师,收到...加仓...加仓....";
} else if (v > 2500) {
state = ": 收到, 嗯... 补了三成...";
} else if (v > 2000) {
state = ": 裤衩快没了, 大佬... 要不要坚持...";
} else {
state = ": 老贼... 我50米长的大刀抽出来必见血,让你先跑49米";
}
std::cout << name << state << std::endl;
}
private:
std::string name;
LiDaXiao *ObjState;
};
class LiDaZui : public Chives {
public:
LiDaZui(const std::string nm, LiDaXiao *obj) : name(nm), ObjState(obj)
{
ObjState->Attach(this);
}
~LiDaZui()
{
ObjState->Dettach(this);
}
void Update()
{
uint32_t v = ObjState->SMarket.GetVal();
std::string state;
if (v > 3000) {
state = ": 好的,老师,了解...八成仓位了...";
}
else if (v > 2500) {
state = ": 好的, 满仓干...";
}
else if (v > 2000) {
state = ": 咱可是本家啊, 大佬... 还有几个底...";
}
else {
state = ": 子弹不长眼,一路走好...";
}
std::cout << name << state << std::endl;
}
private:
std::string name;
LiDaXiao *ObjState;
};
class LuRenJia : public Chives{
public:
LuRenJia(const std::string nm, LiDaXiao *obj) : name(nm), ObjState(obj)
{
ObjState->Attach(this);
}
~LuRenJia()
{
ObjState->Dettach(this);
}
void Update()
{
uint32_t v = ObjState->SMarket.GetVal();
std::string state;
if (v > 2500) {
state = ": 看好你哦, 满仓干...";
} else if (v > 2000) {
state = ": 割了,割了.....下雨路滑...";
} else {
state = ": 真割了,八年后老子又是一茬韭菜...";
}
std::cout << name << state << std::endl;
}
private:
std::string name;
LiDaXiao *ObjState;
};
CPP文件:Observer.cpp
#include "Observer.h"
using namespace std;
int main()
{
LiDaXiao *ldx = new LiDaXiao("李大霄");
WangDaChui *wdc = new WangDaChui("王大锤", ldx);
LiDaZui *ldz = new LiDaZui("李大嘴", ldx);
ldx->PullCalf(4500);
ldx->PullCalf(2800);
delete ldz;
LuRenJia *lrj = new LuRenJia("路人甲", ldx);
ldx->PullCalf(2200);
ldx->PullCalf(800);
delete wdc;
delete lrj;
delete ldx;
return 0;
}