观察者模式(行为型)
一、目的
系统中相互协作的模块之间常会有一个副作用:维护对象之间的一致性而导致对象间的紧耦合。
为解决这个问题,需要定义一种一对多的依赖关系,当一个对象发生变化时,所有依赖它的对象都得到通知,并自动执行相关操作。由此可知,观察者模式是一个发布-订阅式模型。被依赖的对象为发布者,对它依赖的对象订阅它的变化用于后续做出反应。
二、应用场景
1)一个抽象模型有两个方面,其中一个方面依赖于另一个方面,需要将其二者封装进不同对象,且独立的变化和复用;
2)一个对象的改变需要告知其它对象,但是不知道需要告知多少对象;
3)一个对象的改变需要告知其它对象,但是不知道是那种对象(松耦合)。
三、组成
- 事件
需求:同时向多个管着这发布状态变化;
功能:提供添加、删除观察者对象的接口; - 观察者
为向自身发布状态变化的对象提供一个统一的反馈接口; - 具体事件
保存具体的事件;
向他的观察者发送变化; - 具体观察者
泛化反应函数,做出具体反应;
四、牛刀小试
1)既定场景
模拟在雨天和晴天里,人和蚂蚁的反应。
人物 | 场景 | 动作 |
---|---|---|
人 | 晴天 | 去钓鱼 |
人 | 雨天 | 最好有伞再出门 |
蚂蚁 | 晴天 | 出去找吃的 |
蚂蚁 | 雨天 | 找材料保护蚁洞 |
2)show you the code
1)observer.h
#include <iostream>
#include <string>
#include <vector>
#include <set>
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
class Event;
class Rain;
class Sunny;
enum EventType{
E_RAINS = 1,
E_SUNNY = 2
};
//Observer
class Observer{
public:
virtual ~Observer();
public:
//offer a single interface to react for the changes conveyed from the event
virtual void Update(EventType);
};
//Concrete Observer:People
class People : public Observer{
public:
People();
~People();
public:
//Override the react interface to deal the concreate event
void Update(EventType);
};
//Concrete Observer: Ant
class Ant : public Observer{
public:
Ant();
~Ant();
public:
void Update(EventType);
};
//Event
class Event{
public:
Event(EventType);
virtual ~Event();
public:
//send status changes to observers
virtual void Notify();
//take base class pointer type as parameter for loose coupling
virtual void Attach(Observer *);
virtual void Detach(Observer *);
private:
EventType m_type;
//decoupling the observers' class and amount
std::vector<Observer*> *m_observers;
};
//Concrete event:rain
class Rain : public Event{
public:
Rain(EventType type);
~Rain();
public:
void Rains();
};
class Sunny : public Event{
public:
Sunny(EventType type);
~Sunny();
public:
void Shine();
};
#endif
2)observer.cpp
#include "observer.h"
//**********************************Observers***********************************
Observer::~Observer(){}
void Observer::Update(EventType type)
{
}
//-------------------------------------------------------------------------------
People::People(){}
People::~People(){}
void People::Update(EventType type)
{
switch (type)
{
case E_RAINS:
std::cout << "It rains, I'd better not go out, unless having an umbrella." << std::endl;
break;
case E_SUNNY:
std::cout << "It gets sunny, going to fishing may be a good idea. " << std::endl;
break;
default:
break;
}
}
//---------------------------------------------------------------------------------
Ant::Ant(){}
Ant::~Ant(){}
void Ant::Update(EventType type)
{
switch (type)
{
case E_RAINS:
std::cout << "It rains, get some material to protect my hole. " << std::endl;
break;
case E_SUNNY:
std::cout << "It gets sunny, it's time to hang out and search something to eat. " << std::endl;
break;
default:
break;
}
}
//********************************Event***************************************
Event::Event(EventType type)
{
m_observers = new std::vector<Observer*>;
m_type = type;
}
Event::~Event()
{
delete m_observers;
}
void Event::Notify()
{
for(std::vector<Observer*>::iterator it = m_observers->begin(); it != m_observers->end(); ++it)
{
(*it)->Update(m_type);
}
}
void Event::Attach(Observer *observer)
{
m_observers->push_back(observer);
}
void Event::Detach(Observer* observer)
{
m_observers->pop_back();
}
//---------------------------------------------------------------------------------------
Rain::Rain(EventType type):Event(type){}
Rain::~Rain(){}
void Rain::Rains()
{
std::cout << "I am rain, and I am going to rain. " << std::endl;
Notify();
}
//---------------------------------------------------------------------------------------
Sunny::Sunny(EventType type):Event(type){}
Sunny::~Sunny(){}
void Sunny::Shine()
{
std::cout << "I am sunny day, and I am going to shine you. " << std::endl;
Notify();
}
3)main.cpp
#include <unistd.h>
#include "observer.h"
int main(int argc, char **argv)
{
Ant ant;
People people;
Rain rain(E_RAINS);
Sunny sunny(E_SUNNY);
rain.Attach(&ant);
rain.Attach(&people);
sunny.Attach(&ant);
sunny.Attach(&people);
sleep(3);
rain.Rains();
sleep(3);
sunny.Shine();
return 0;
}
4)makefile
all:
g++ -I. observer.cpp main.cpp -o observer.out
.PHONY:clean
clean:
rm -f observer.out
五、说明
代码结构不符合开发规范,仅作为对模式的理解与练习。欢迎在评论区发表见解,共同进步。