1.意图

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

2.别名

依赖(Depenents),发布-订阅(Publish-subscribe)

3.动机

一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得到通知。作为这个通知的响应,每个观察者都将查询目标以使其状态于目标的同步。

4.适用性

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使它们可以各自独立改变和复用。
  • 当一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧耦合的。

5.结构

6.代码实例

//Subject.h

#include <memory>
#include <vector> class AbstractObserver; class AbstractSubject
{
public:
virtual void Attach(std::shared_ptr<AbstractObserver> pObserber)=;
virtual void Notify()=;
virtual void SetState(int state)=;
virtual int GetState()=;
}; class ConcreteSubject : public AbstractSubject
{
public:
ConcreteSubject();
~ConcreteSubject();
virtual void Attach(std::shared_ptr<AbstractObserver> pObserber);
virtual void Notify();
virtual void SetState(int state);
virtual int GetState();
private:
std::vector<std::shared_ptr<AbstractObserver>> m_vecObservers;
int m_state;
};
//Observer.h

#include <memory>

class AbstractSubject;

class AbstractObserver
{
public:
virtual void Update()=;
}; class ConcreteObserver1 : public AbstractObserver
{
public:
ConcreteObserver1(std::shared_ptr<AbstractSubject> pSubject);
~ConcreteObserver1();
virtual void Update();
private:
std::shared_ptr<AbstractSubject> m_Subject;
}; class ConcreteObserver2: public AbstractObserver
{
public:
ConcreteObserver2(std::shared_ptr<AbstractSubject> pSubject);
~ConcreteObserver2();
virtual void Update();
private:
std::shared_ptr<AbstractSubject> m_Subject;
}; class ConcreteObserver3 : public AbstractObserver
{
public:
ConcreteObserver3(std::shared_ptr<AbstractSubject> pSubject);
~ConcreteObserver3();
virtual void Update();
private:
std::shared_ptr<AbstractSubject> m_Subject;
};
//Subject.cpp

#include "Subject.h"
#include "Observer.h" ConcreteSubject::ConcreteSubject()
{
} ConcreteSubject::~ConcreteSubject()
{
} void ConcreteSubject::SetState(int state)
{
m_state = state;
} void ConcreteSubject::Attach(std::shared_ptr<AbstractObserver> pObserver)
{
m_vecObservers.push_back(pObserver);
} int ConcreteSubject::GetState()
{
return m_state;
} void ConcreteSubject::Notify()
{
for(auto iter = m_vecObservers.begin(); iter != m_vecObservers.end(); ++iter)
{
(*iter)->Update();
}
}
// Observer.cpp

#include "Observer.h"
#include "Subject.h"
#include <iostream> ConcreteObserver1::ConcreteObserver1(std::shared_ptr<AbstractSubject> pSubject)
: m_Subject(pSubject)
{
} ConcreteObserver1::~ConcreteObserver1()
{
} void ConcreteObserver1::Update()
{
std::cout << "ConcreteObserver1 Updated state:" << m_Subject->GetState() << std::endl;
} ConcreteObserver2::ConcreteObserver2(std::shared_ptr<AbstractSubject> pSubject)
: m_Subject(pSubject)
{
} ConcreteObserver2::~ConcreteObserver2()
{
} void ConcreteObserver2::Update()
{
std::cout << "ConcreteObserver2 Updated state:" << m_Subject->GetState() << std::endl;
} ConcreteObserver3::ConcreteObserver3(std::shared_ptr<AbstractSubject> pSubject)
: m_Subject(pSubject)
{
} ConcreteObserver3::~ConcreteObserver3()
{
} void ConcreteObserver3::Update()
{
std::cout << "ConcreteObserver3 Updated state:" << m_Subject->GetState() << std::endl;
}
//client.cpp

#include "Observer.h"
#include "Subject.h" int main()
{
std::shared_ptr<AbstractSubject> pSubject(new ConcreteSubject); std::shared_ptr<AbstractObserver> pObserver1(new ConcreteObserver1(pSubject));
std::shared_ptr<AbstractObserver> pObserver2(new ConcreteObserver2(pSubject));
std::shared_ptr<AbstractObserver> pObserver3(new ConcreteObserver3(pSubject)); pSubject->Attach(pObserver1);
pSubject->Attach(pObserver2);
pSubject->Attach(pObserver3); pSubject->SetState(); pSubject->Notify(); while();
}

7.测试结果

8.效果

  • 目标和观察者间的抽象耦合
  • 支持广播通信
  • 意外的更新 因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外,如果依赖准则的定义或维护不当,常常会引起错误的更新,这种错误通常难以捕捉。

Observer(观察者)-对象行为型模式的更多相关文章

  1. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  2. 设计模式18:Observer 观察者模式(行为型模式)

    Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...

  3. 设计模式(3)-对象创建型模式-Abstract Factory模式

    1.对象创建型模式 1.3           Abstract Factory模式 1.3.1 需求 在下面情况能够使用Abstract Factory模式: •  一个系统要独立于它的产品的创建. ...

  4. 设计模式(4)-对象创建型模式-Prototype模式

    1.对象创建型模式 1.4          Protoype模式 1.4.1需求 通过拷贝原形对象创建新的对象. 1.4.2结构 •P r o t o t y p e(Gr a p h i c) - ...

  5. 【设计模式】observer(观察者)-- 对象行为型模式5.7

    1.意图 对象之间一对多的依赖关系,当目标对象发生改变时,所有依赖于它的对象都要得到通知并自动更新 2.别名 依赖,发布-订阅 3.动机 1)需要确保相互协作的对象的一致性(数据要保持一致),但一致性 ...

  6. 设计模式--观察者模式Observer(对象行为型)

    一.观察者模式 观察者模式是在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新.观察者模式也被称之为:主题-观察者模式,发布-订阅模式,前者是一,后者是多. ...

  7. singleton(单件)-对象创建型模式

    1.意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 2.动机 对一些类来说,只有一个实例是很重要的.让类自身负责保存它唯一的实例,这个类可以保证没有其他实例可以被创建(通过截取创建新对象 ...

  8. 迭代器模式/iterator模式/对象行为型模式

    意图 又名:游标(Cursor): 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示. 动机 一个聚合对象,提供访问元素的方法,而有不暴露它的内部结构.如list,将对列表的访问 ...

  9. Mediator(中介者)-对象行为型模式

    1.意图 用一个中介对象来封装一系列的对象交互.中介者使各个对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 2.动机 通过将集体行为封装在一个单独的中介者对象中,中介者 ...

随机推荐

  1. jpeg库编译 - windows平台

    一.准备: 下载最新的jpeg库源码:http://www.ijg.org/files/jpegsr9a.zip二.编译 1. 解压到指定目录 2. 打开VS2010命令行窗口(为了得到VS2010的 ...

  2. android 绑定spinner键值对显示内存地址的问题

    初学android,估计是.net学傻了,觉得android好麻烦. 绑定下拉菜单Spinner键值对. 参照这篇文章,地址:http://blog.csdn.net/shouliang52000/a ...

  3. .net 中select和where的区别

    Select(p=>p.ID==id) 这里选择的结果是通过p,访问迭代器,然后选取的是p.ID==id的结果,选择到的是bool对象 Where(p=>p.ID==id) 这里是过滤,p ...

  4. 在VMware下正确克隆CentOS6.5的打开方式

    引言 想必用VMware Workstation软件安装虚拟机,作为一个爱"折腾"的攻城狮肯定是千千万万遍的事情.无论是学习还是工作之中,我们都会遇到需要在一台物理主机上运行多台虚 ...

  5. 【MongoDB】MongoDB 3.2 SCRAM-SHA-1验证方式

    新版本已取消addUser方法,改使用createUser方法 官方地址:https://docs.mongodb.com/manual/tutorial/create-users/ 官方地址:htt ...

  6. [转载]Python 资源大全

    原文链接:Python 资源大全 环境管理 管理 Python 版本和环境的工具 p – 非常简单的交互式 python 版本管理工具. pyenv – 简单的 Python 版本管理工具. Vex  ...

  7. Web后台技术趋势

    今天使用Google Trend比较了一下服务器端的程序开发语言技术ASP/ASP.NET Core, PHP, Node.Js的变化趋势,发现一下特点. ASP.NET最近几年一直再下降. ASP和 ...

  8. 修改tomcat应用日志默认编码格式

    前言 今天开发跟我说tomcat日志中的中文不能正常显示,根据以往的经验,我觉得可能跟服务器的编码有关,于是尝试各种方法,但还是没能解决问题. 后来我突然想到会不会跟tomcat的设置有关呢,于是在网 ...

  9. requirejs的使用

    requirejs的优点: 1.防止在js的加载过程中,阻止页面的渲染: 2.可以引入多个js文件: 3.可以写出重复使用的js模块: 4.有效的防止命名的冲突,通过将变量分装在模块中的方式实现: r ...

  10. javascript检查移动设备是否支持重力方向感应

    javascript如何检查移动设备,如手机平台是否支持重力或者方向感应. 可以使用html5提供的重力和方向感应接口来判断. html5 中针对高端手机提供了重力感应和重力加速的接口,开发可以利用这 ...