文章目录
前言
在现实世界中,许多对象是互相联系的。当其中一个对象的状态发生改变,可能会导致一个或者多个其他对象的行为也发生改变。例如,某种商品的物价上涨时,其上游和下游产品也都会相应的变化;当我们开车通过交叉路口时,红灯j就要停,遇到绿灯会行。
Observer 模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer 模式就是解决了这一个问题。
一、观察者模式(Observer模式)
Subject 提供依赖于它的观察者 Observer 的添加(Attach)和删除(Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作(Notify)。观察者 Observer 则提供一个 Update 操作,注意这里的 Observer 的 Update 操作并不在 Observer 改变了 Subject 目标状态的时候就对自己进行更新,这个更新操作要延迟到 Subject 对象发出 Notify 通知所有Observer 进行修改(调用 Update),即做到“先通知后修改”。UML图如下:
二、具体源码
1.Subject.h
代码如下(示例):
#ifndef _SUBJECT_H_
#define _SUBJECT_H_
#include <iostream>
#include <list>
#include <string>
//定义别名
typedef std::string State;
class Observer;
class Subject
{
public:
virtual ~Subject();
//添加观察者对象
virtual void Attach(Observer* obv);
//删除观察者对象
virtual void Detach(Observer* obv);
//状态发生改变后,通知观察者对象
virtual void Notify();
virtual void Notify1();
//设置内部状态
virtual void SetState(const State& st) = 0;
//提供对外接口,便于获取内部状态
virtual State GetState() = 0;
protected:
Subject();
private:
//存储观察者对象的容器
std::list<Observer* >* _obvs;
};
class ConcreteSubject :public Subject
{
public:
ConcreteSubject();
~ConcreteSubject();
State GetState();
void SetState(const State& st);
protected:
private:
State _st;
};
#endif //_SUBJECT_H_
2.Subject.cpp
代码如下(示例):
#include "Subject.h"
#include "Observer.h"
Subject::Subject()
{
//****在模板的使用之前一定要 new,创建,申请内存
_obvs = new std::list<Observer*>;
}
Subject::~Subject()
{
}
void Subject::Attach(Observer* obv)
{
//添加观察者对象
_obvs->push_front(obv);
}
void Subject::Detach(Observer* obv)
{
//删除观察者对象
if (obv != NULL)
_obvs->remove(obv);
}
void Subject::Notify()
{
//遍历容器,通知观察者对象更新
for (auto it:(*_obvs))
{
it->Update(this);
}
}
void Subject::Notify1()
{
//遍历容器,通知观察者对象更新
for (auto it : (*_obvs))
{
it->Update(this->GetState());
}
}
ConcreteSubject::ConcreteSubject()
{
_st = '\0';
}
ConcreteSubject::~ConcreteSubject()
{
}
State ConcreteSubject::GetState()
{
return _st;
}
void ConcreteSubject::SetState(const State& st)
{
_st = st;
}
3.Observer.h
代码如下(示例):
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include "Subject.h"
class Observer
{
public:
virtual ~Observer();
virtual Subject* GetSubject() =0;
//更新内部状态
virtual void Update(Subject* sub) = 0;
//实现接口的重定义
virtual void Update(State st) = 0;
virtual void PrintInfo() = 0;
protected:
Observer();
State _st;
private:
};
class ConcreteObserverA :public Observer
{
public:
virtual Subject* GetSubject();
ConcreteObserverA(Subject* sub);
virtual ~ConcreteObserverA();
//Subject作为参数,这样可以让一个observer可以观察Subject。
void Update(Subject* sub);
void Update(State st);
void PrintInfo();
protected:
private:
Subject* _sub;
};
class ConcreteObserverB :public Observer
{
public:
virtual Subject* GetSubject();
ConcreteObserverB(Subject* sub);
virtual ~ConcreteObserverB();
//Subject作为参数,这样可以让一个observer可以观察Subject。
void Update(Subject* sub);
void Update(State st);
void PrintInfo();
protected:
private:
Subject* _sub;
};
#endif //_OBSERVER_H_
4.Observer.cpp
代码如下(示例):
#include "Observer.h"
Observer::Observer()
{
_st = '\0';
}
Observer::~Observer()
{
}
ConcreteObserverA::ConcreteObserverA(Subject* sub)
{
_sub = sub;
_sub->Attach(this);
}
ConcreteObserverA::~ConcreteObserverA()
{
_sub->Detach(this);
if (_sub != 0)
{
delete _sub;
}
}
Subject* ConcreteObserverA::GetSubject()
{
return _sub;
}
void ConcreteObserverA::PrintInfo()
{
std::cout << "ConcreteObserverA observer.... "<<this->_st<<std::endl;
}
void ConcreteObserverA::Update(Subject* sub)
{
_st = sub->GetState();
PrintInfo();
}
void ConcreteObserverA::Update(State st)
{
_st = st;
PrintInfo();
}
ConcreteObserverB::ConcreteObserverB(Subject* sub)
{
_sub = sub;
_sub->Attach(this);
}
ConcreteObserverB::~ConcreteObserverB()
{
_sub->Detach(this);
if (_sub != 0)
{
delete _sub;
}
}
Subject* ConcreteObserverB::GetSubject()
{
return _sub;
}
void ConcreteObserverB::PrintInfo()
{
std::cout << "ConcreteObserverB observer.... "<<this->_st<<std::endl;
}
void ConcreteObserverB::Update(Subject* sub)
{
_st = sub->GetState();
PrintInfo();
}
void ConcreteObserverB::Update(State st)
{
_st = st;
PrintInfo();
}
5.main.cpp
代码如下(示例):
#include "Subject.h"
#include "Observer.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
ConcreteSubject* sub = new ConcreteSubject();
Observer* o1 = new ConcreteObserverA(sub);
Observer* o2 = new ConcreteObserverB(sub);
//通过subject对象通知观察者
sub->SetState("old");
sub->Notify();
//直接通知观察者 内部信息
sub->SetState("new");
sub->Notify1();
return 0;
}
在 Observer 模式的实现中,Subject 维护一个list作为存储其所有观察者的容器。每当调用Notify操作就遍历list中的Observer对象,并广播通知改变状态(调用Observer的Update操作)。
三、运行结果
Observer模式运行结果如下:
总结
Observer 模式是影响极为深远的模式之一,也是在大型系统开发过程中要用到的模式之一。Observer模式的本质是构建多个对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。因此,也称为发布-订阅(publish-subscribe),目标就是通知的发布者,观察者则是通知的订阅者(接受通知)。
该设计模式的好处是降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系,而且在目标与观察者之间建立了一套触发机制。但是,目标与观察者之间的依赖关系并没有完全解除,当观察者对象很多时,通知的发布会花费很多时间,降低程序的效率。
本文参考《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》,对内容进行整理,方便大家学习。如想学习详细内容,请参考此书。