设计模式【16】——观察者模式(Observer模式)


前言

在现实世界中,许多对象是互相联系的。当其中一个对象的状态发生改变,可能会导致一个或者多个其他对象的行为也发生改变。例如,某种商品的物价上涨时,其上游和下游产品也都会相应的变化;当我们开车通过交叉路口时,红灯j就要停,遇到绿灯会行。
Observer 模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer 模式就是解决了这一个问题。


一、观察者模式(Observer模式)

Subject 提供依赖于它的观察者 Observer 的添加(Attach)和删除(Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作(Notify)。观察者 Observer 则提供一个 Update 操作,注意这里的 Observer 的 Update 操作并不在 Observer 改变了 Subject 目标状态的时候就对自己进行更新,这个更新操作要延迟到 Subject 对象发出 Notify 通知所有Observer 进行修改(调用 Update),即做到“先通知后修改”。UML图如下:
Observer模式示意图


二、具体源码

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 模式是影响极为深远的模式之一,也是在大型系统开发过程中要用到的模式之一。Observer模式的本质是构建多个对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。因此,也称为发布-订阅(publish-subscribe),目标就是通知的发布者,观察者则是通知的订阅者(接受通知)。
该设计模式的好处是降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系,而且在目标与观察者之间建立了一套触发机制。但是,目标与观察者之间的依赖关系并没有完全解除,当观察者对象很多时,通知的发布会花费很多时间,降低程序的效率。


本文参考《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》,对内容进行整理,方便大家学习。如想学习详细内容,请参考此书。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

希望早日退休的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值