介绍
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。[DP]
- Subject被观察者
定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。 - Observer观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。 - ConcreteSubject具体的被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。 - ConcreteObserver具体的观察者
每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑。
优点:观察者和被观察者之间是抽象耦合;建立一套触发机制
应用:关联行为场景。需要注意的是,关联行为是可拆分的,而不是组合关系;事件多级触发场景;跨系统的消息交换场景,如消息队列的处理机制
注意:广播连,消息最多转发一次(传递两次)
UML类图
简单示例代码:
#ifndef SIMPLE_OBSERVER_H
#define SIMPLE_OBSERVER_H
#include <iostream>
#include <list>
#include <string>
using namespace std;
/**
* @brief The Observer class
* 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
* 抽象观察者一般用一个抽象类或者一个接口实现,通常包含一个Update()方法
*/
class Observer
{
public:
virtual void update()
{
cout<<"Observer::update()"<<endl;
}
};
/**
* @brief The Subject class
* 抽象通知者,它把所有对观察者对象的引用保存在一个聚集里
*/
class Subject
{
public:
void attach(Observer *ob)
{
m_observers.push_back(ob);
}
void detach(Observer *ob)
{
m_observers.remove(ob);
}
void notify()
{
for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
(*it)->update();
}
}
private:
list<Observer *> m_observers;
};
/**
* @brief The ConcreteSubject class
* 具体通知者
*/
class ConcreteSubject : public Subject
{
public:
//具体被观察者的状态
string getSubjectState()
{
return m_subjectState;
}
void setSubjectState(string stateStr)
{
m_subjectState = stateStr;
}
private:
string m_subjectState;
};
/**
* @brief The ConcreteObserver class
* 具体观察者
*/
class ConcreteObserver : public Observer
{
public:
ConcreteObserver(ConcreteSubject *subject , string name)
{
m_subject = subject;
m_name = name;
}
void update()
{
m_observerState = m_subject->getSubjectState();
cout<<"观察者:"<<m_name<<"的状态是:"<<m_observerState<<endl;
}
private:
string m_name ;
string m_observerState;
ConcreteSubject *m_subject;
};
#endif // SIMPLE_OBSERVER_H
调用代码:
ConcreteSubject *s = new ConcreteSubject;
s->attach(new ConcreteObserver(s , "X"));
s->attach(new ConcreteObserver(s , "Y"));
s->attach(new ConcreteObserver(s , "Z"));
s->setSubjectState("ABC");
s->notify();
s->setSubjectState("BCD");
s->notify();
delete s;
s = nullptr;
《大话设计模式种,公司前台场景代码》
#ifndef COMPANY_OBSERVER_H
#define COMPANY_OBSERVER_H
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Subject;
/**
* @brief The Observer class
* 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
* 抽象观察者一般用一个抽象类或者一个接口实现,通常包含一个Update()方法.
*
* 创建该观察者同时,提供一个抽象通知者,因为此时通知者有可能会变。
*/
class Observer
{
public:
Observer(Subject *sub , string name)
{
m_subject = sub;
m_name = name;
}
virtual void update()
{
cout<<"Observer::update()"<<endl;
}
protected:
string m_name ;
Subject *m_subject;
};
/**
* @brief The Subject class
* 抽象通知者,它把所有对观察者对象的引用保存在一个聚集里
* 因为此时的通知者不知是:前台 还是 老板
*/
class Subject
{
public:
void virtual attach(Observer *ob) = 0;
void virtual detach(Observer *ob) = 0;
void virtual notify() = 0;
void virtual setAction(string act) = 0;
string virtual getAction() const = 0;
};
/***********************************具体的通知者*****************************************/
/**
* @brief The Boss class
* 具体的通知者:老板自己回来了,前台美女不在
*/
class Boss : public Subject
{
public:
void attach(Observer *ob)
{
m_observers.push_back(ob);
}
void detach(Observer *ob)
{
m_observers.remove(ob);
}
void notify()
{
for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
(*it)->update();
}
}
void setAction(string act)
{
m_action = act;
}
string getAction() const
{
return m_action;
}
private:
list<Observer *> m_observers;
string m_action;
};
/**
* @brief The Secretary class
* 具体的通知者:老板回来了,前台美女在
*/
class Secretary : public Subject
{
public:
void attach(Observer *ob)
{
m_observers.push_back(ob);
}
void detach(Observer *ob)
{
m_observers.remove(ob);
}
void notify()
{
for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
(*it)->update();
}
}
void setAction(string act)
{
m_action = act;
}
string getAction() const
{
return m_action;
}
private:
list<Observer *> m_observers;
string m_action;
};
/***********************************具体的观察者******************************************/
/**
* @brief The StockObserver class
* 具体的观察者:看股票的同事
*/
class StockObserver : public Observer
{
public:
StockObserver(Subject *sub , string name )
:Observer(sub , name)
{
}
void update() override
{
cout<<m_subject->getAction()<<" "<<m_name<<" 关闭股票软件,继续工作。\n";
}
};
/**
* @brief The GameObserver class
* 具体的观察者:玩游戏的同事
*/
class GameObserver : public Observer
{
public:
GameObserver(Subject *sub , string name )
:Observer(sub , name)
{
}
void update() override
{
cout<<m_subject->getAction()<<" "<<m_name<<" 停止玩游戏,继续工作。\n";
}
};
/**
* @brief The NBAObserver class
* 具体的观察者:看NBA的同事
*/
class NBAObserver : public Observer
{
public:
NBAObserver(Subject *sub , string name )
:Observer(sub , name)
{
}
void update() override
{
cout<<m_subject->getAction()<<" "<<m_name<<" 停止观看NBA,继续工作。\n";
}
};
#endif // COMPANY_OBSERVER_H
调用代码:
/*
//具体的通知者
Boss *pHuhansan = new Boss;
//老板回来,前台不在
//看股票的同事
StockObserver *pSo = new StockObserver( pHuhansan , "易小天");
//看NBA的同事
NBAObserver *pNo = new NBAObserver(pHuhansan , "赵高");
//玩游戏的同事
GameObserver *pGo = new GameObserver(pHuhansan , "项羽");
//老板添加观察者
pHuhansan->attach(pSo);
pHuhansan->attach(pNo);
pHuhansan->attach(pGo);
pHuhansan->setAction("胡汉三我回来了");
pHuhansan->notify();
*/
//老板回来,前台在
Secretary *pMeimei = new Secretary;
//看股票的同事
StockObserver *pSo = new StockObserver( pMeimei , "易小天");
//看NBA的同事
NBAObserver *pNo = new NBAObserver(pMeimei , "赵高");
//玩游戏的同事
GameObserver *pGo = new GameObserver(pMeimei , "项羽");
//前台添加观察者,关系不好的不让加
pMeimei->attach(pSo);
pMeimei->attach(pNo);
pMeimei->attach(pGo);
pMeimei->setAction("胡汉三大佬回来啦啦啦~~~");
pMeimei->notify();
随着对该模式理解的深入,会随时更新该篇博客。
部分内容摘自网络,若有侵权,联系删除。