姓名:刘欢 学号:19020100155 学院:电子工程学院 班级:1902012
原文转自:https://zhuanlan.zhihu.com/p/110142284
【嵌牛导读】我们常常说嵌入式观察,那具体如何观察,观察什么现象,为什么要进行嵌入式观察,本文将详细讲解嵌入式的观察者模式。
【嵌牛鼻子】嵌入式观察
【嵌牛提问】什么是嵌入式观察,嵌入式观察的作用是什么?
【嵌牛正文】
一、 基本信息
什么是观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,会通知所有观察者,使观察者自己可以更新自己。
观察者模式特点(☆☆☆☆☆)
①什么时候使用观察者模式
当一个对象改变需要同时改变其他对象的时候。
当不知道有多少具体对象需要改变时,使用观察者模式。
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
②观察者模式作用
主要是在解耦。让耦合的双方都依赖于抽象,而不依赖于具体(抽象耦合)。从而使各自的变化不会影响到另一边的变化(依赖倒转原则)。并建立了一套触发机制。
个人理解,主要还是通过抽象基类进行解耦。
③缺点
如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
更新接口(update)只能统一调用,实际中并不一定统一。
二、 程序实现
IDE使用Qt
具体实现
抽象观察者,为具体观察者定义update接口,在得到主题通知时更新自己。
class Observer
{
public:
Observer() {}
virtual ~Observer() {}
virtual void update() = 0;
};
抽象主题为独立模块,仅与抽象观察者耦合,维护观察者列表,向众多观察者广播事件。
class Subject
{
public:
Subject() {}
virtual ~Subject() {}
public:
//增加观察者
void attachObserver(Observer *observer) {m_observersList.push_back(observer);}
//移除观察者
void detachObserver(Observer *observer) {m_observersList.remove(observer);}
//通知
void notifyObsever()
{
//C++11增加了range-for用法,简化了遍历写法
for(Observer *iter : m_observersList) { iter->update(); }
}
private:
//具体观察者列表
list
};
具体主题,设置相关状态,并将状态传递给具体观察者。
class ConcreteSubject : public Subject
{
public:
ConcreteSubject() {}
virtual ~ ConcreteSubject() {}
public:
void setSubjectState(const string state) {m_subjectState = state;}
string getSubjectState() {return m_subjectState;}
private:
string m_subjectState;
};
具体观察者,实现抽象观察者的update接口,使自身状态与主题状态一致。具体观察者需要保存相关具体主题,也可以保存多个。类似于可以关注多个公众号。
class ConcreteObserver : public Observer
{
public:
ConcreteObserver(ConcreteSubject *concreteSubject, string name):
m_observerName(name),m_concreteSubject(concreteSubject) {}
virtual ~ ConcreteObserver() {}
public:
virtual void update()
{
//观察者状态由发布者提供
m_observerState = m_concreteSubject->getSubjectState();
std::cout << "Observer " << m_observerName << " status is " << m_observerState << std::endl;
}
private:
string m_observerName; //观察者名称
string m_observerState; //所观察的具体主题,可观察多个
ConcreteSubject *m_concreteSubject;
};
2. 具体调用
int main(int argc, char *argv[])
{
ConcreteSubject *s = new ConcreteSubject();
ConcreteObserver *observerA = new ConcreteObserver(s, "A");
//添加3个观察者,更新状态并通知
s->attachObserver(observerA);
s->attachObserver(new ConcreteObserver(s, "B"));
s->attachObserver(new ConcreteObserver(s, "C"));
s->setSubjectState("start learn!");
s->notifyObsever();
//移除观察者A,更新状态并通知
s->detachObserver(observerA);
s->setSubjectState("stop learn!");
s->notifyObsever();
QCoreApplication a(argc, argv);
return a.exec();
}
三、小结
直接看观察者模式的实现所获得的东西可能没有那么多,而且需要看很多遍,每次会有新的感悟。不妨看看大话设计模式的例子,从耦合的例子开始,看到最后面对这样一个需求是如何从耦合变得不那么耦合。有点数学定理公式,直接告诉你结果,但是却不知道来源与具体应用场景。