1.意图

对象之间一对多的依赖关系,当目标对象发生改变时,所有依赖于它的对象都要得到通知并自动更新

2.别名

依赖,发布-订阅

3.动机

1)需要确保相互协作的对象的一致性(数据要保持一致),但一致性会使各个对象紧密耦合,减低它们的可重用性。

2)Observer模式描述了如何建立这种关系:一个目标(Subject)可以有任意个依赖于它的观察者(Observer),当目标发生改变的时候,所有观察者都得到通知(Notify);观察者响应通知(Update),会去查询目标状态(GetState)使其状态与目标状态同步一致。

3)观察者去订阅(Subscribe),目标去发布(Publish)

4.适用性

1)一个抽象模型有两方面,一方面依赖于另一方面,两者独立封装在不同对象里以方便各自独立的改变和复用

2)一个对象的改变需要通知另一个对象,而被通知的对象数量不确定

3)被通知的对象之间互相不知道对方是谁,没有紧密耦合

5.结构 & 6.参与者

7.协作

8.效果

1)目标与观察者之间的抽象耦合:目标不知道具体观察者是属于哪个类的,只知道他们符合抽象Subject的接口,具体目标本身也可以是各式各样的,只要符合Object抽象接口即可,所以耦合是抽象和最小的,目标和观察者可以属于整个系统中的任意一个层次。

2)支持广播通信:目标可以无脑广播给所有它的观察者,不用知道观察者是谁,是否响应处理通知可以放在观察者层去判断

3)意外的更新:A观察者不知道B观察者的存在,A的操作导致目标改变,会通知到B,若B其实不依赖目标(定义了错误的依赖关系)可能会导致大量无效的通知或者通知导致B观察者数据错误

9.实现

1)创建目标与观察者之间的映射:

  方法1:在目标里面存放观察者列表,简单,但目标多观察者少的时候存储代价会高一些

  方法2:用一个公共的对象来存储subjects 和 observers之间的映射

2)观察多个目标:

  Update里面传参数Subject,来告知观察者是哪个目标更新了

3)谁触发更新:

  方式1:目标对象的属性变更时由目标触发更新通知,好处观察者和其他对象不用关心何时触发更新不会出现遗漏,缺点是一个操作可能会导致多次更新,也会发多次通知

  方式2:由客户来触发更新通知,好处可以随时控制触发更新时机,避免中间更新,缺点会遗漏触发

4)对已删除目标的悬挂引用:

  通知目标的所有观察者把目标从身上的引用移除

5)在发出通知前确保目标的状态自身是一致的:

  方式1:Subject上的Notify在SetState之后调用,因为Observer里面的Update可能会从Subject上GetState

  方式2:用Template Method模式,即父类Subject中的模板方法把重定义操作Operation()放在Notify()之前,子类只要重定义Operation方法即可,就能确保操作完了才Notify

6)通知模型 推/拉

  push推模型:把详细信息都通知给所有观察者,不管他们是否需要;推模型假定知道观察者需要什么,但假定不一定正确可能使得观察者难以复用(收到了大量无用信息,自己想要的又没有推送)

  pull拉模型:只发送最小通知(如告诉观察者有更新了),观察根据自己需要从目标取他想要的数据;拉模型假定目标不知道观察者,但效率会低,因为在目标发送信息太少的情况下观察者无法知道目标到底改变了什么

7)显式的指定关心内容

  void Subject::Attach(Observer *, Aspect& interest);  观察者注册时指定关心的目标方面变更,目标只通知关心改变方面的观察者,并在Update里把Subject和Aspect都带上

  这个操作在Observer端做筛选其实也行。

8)封装复杂的更新语义

  更新管理器ChangeManager的职责,是个Mediator,Singleton

  a) 它将一个目标映射到它的观察者并提供一个接口来维护这个映射。这就不需要由目标来维护对其观察者的引用, 反之亦然。

  b) 它定义一个特定的更新策略。(比如N个目标都改变了才触发通知,或者目标在400ms发生改变只触发一次)

  c) 根据一个目标的请求, 它更新所有依赖于这个目标的观察者。

9)结合目标类和观察者类:

  两者可以放到一个类里

10.日常开发项目应用

1)跨服逻辑,gameserver是观察者,centerserver是目标;gameserver连上后会Attach到centerserver,断开就Detach, centerserver上的globalserver列表发生更新的时候需要Notify所有的gameserver,用于更新PK服列表信息

2)战斗逻辑,player是观察者,player和monster是目标entity;entity进入player可视范围Attach,离开Detach,entity移动后坐标发生变更,需要通知他周围的观察者player坐标变更,这里使用了ChangeManager(map)来管理这个依赖关系的映射,并且制定了更新策略:发生变更不立马通知,400ms tick的时候如果有变更则通知观察者

【设计模式】observer(观察者)-- 对象行为型模式5.7的更多相关文章

  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. Java经典设计模式之十一种行为型模式

    转载: Java经典设计模式之十一种行为型模式 Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式 ...

  6. Java设计模式——Observer(观察者)模式

    在多个对象之间建立一对多的关系,以便当一个对象状态改变的时候.其它全部依赖于这个对象的对象都能得到通知,并被自己主动更新. 适用情况: 当一个抽象模型有两个方面,当中一个方面依赖于还有一方面. 将这二 ...

  7. Java经典设计模式之十一种行为型模式(附实例和详解)

    Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:Java经典设计模式之 ...

  8. Java设计模式之十一种行为型模式(附实例和详解)

    Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:J设计模式之五大创建型 ...

  9. java架构之路-(设计模式)五种创建型模式之单例模式

    设计模式自身一直不是很了解,但其实我们时刻都在使用这些设计模式的,java有23种设计模式和6大原则. 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可 ...

  10. Java设计模式16:常用设计模式之观察者模式(行为型模式)

    1. Java之观察者模式(Observer Pattern) (1)概述: 生活中我们在使用新闻app,当我们对某一栏比较感兴趣,我们往往会订阅这栏新闻,比如我对军事栏感兴趣,我就会订阅军事栏的新闻 ...

随机推荐

  1. Linux磁盘及文件系统(一)

    一.磁盘 1.IO接口类型 (1)传输类型分类 并口:同一个线缆可以接多块设备 IDE口:两个,一个主设备,一个从设备 SCSI:宽带:16-1:窄带:8-1 串口:同一个线缆只可以接一个设备 (2) ...

  2. [RHEL] 配置 LVM 卷

    [RHEL] 配置 LVM 卷 一.Introduction 基础预览 :LVM 认知与扩容操作 高端实战:Linux系统如何迁移至LVM磁盘 之前转过一篇文章 LVM分区在线扩容 ,其原因是我需要给 ...

  3. 爬虫2:urllib

        了解即可,不好用   一. 概述   python内置的http请求库,包括4个模块,分别如下   urllib.request   请求模块 urllib.error       异常处理模 ...

  4. 写给移动开发者的 React Native 指南

    本文原创版权归 简书 wingjay 所有,如有转载,请于文章篇头位置显示标注原创作者及出处,以示尊重! 作者:wingjay 出处:http://www.jianshu.com/p/b8894425 ...

  5. 总结day04 ---- 列表的切片,增删改查,以及,相关方法, 元祖的使用方法

    内容大纲 1 : 列表的索引 : 列表的切片 2 : 列表的增加内容 >1:append(char)  >2:insert(index,char) >3:extend('可迭代对象' ...

  6. 什么是马拉车算法(Manacher's Algorithm)?

    提出问题 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字符串正着读和反着读是一样的,那它就是回文串.如a.aa.aba.abba等. 暴力解法 简单粗暴:找到字符串的所有子串, ...

  7. ThreadLocal系列(一)-ThreadLocal的使用及原理解析

    ThreadLocal系列之ThreadLocal(源码基于java8) 项目中我们如果想要某个对象在程序运行中的任意位置获取到,就需要借助ThreadLocal来实现,这个对象称作线程的本地变量,下 ...

  8. 02-url路由分配及模板渲染方式

    本章主要内容 1.url基本概念及格式 2.path和re_path 3.模板路径配置 4.模板渲染方式 1.url基本概念及格式 URL(uniform Resoure Locator)统一资源定位 ...

  9. tomcat startup.brt启动一闪而过

    今天启动皕杰自带的tomcat的时候,直接点startup.brt控制台窗口一闪而过. 改用cmd命令启动: 切换到 E:\皕杰报表\皕杰报表3.5\DemoServer\bin目录 运行startu ...

  10. symfony4 404页面未找到

    symfony4 404页面未找到 安装好symfony4后,发现除了首页能正常显示,其他页面如/_profiler_/等其他创建的router访问都显示The requested URL /xxx ...