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. 实时监测input输入变化 jQuery

    $('#production_name').on('input propertychange',function(){ alert('输入一个字弹一回'); });

  2. 如何实现三个div都自适应(滴滴面试题)

    <div class="table"> <div class="accordant"> <div class="box& ...

  3. TCP 和 UDP 协议

    TCP 和 UDP 协议 一.socket层 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐 ...

  4. mybaits中"#"和"$"的区别

    动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析.mybatis 为我们提供了两种支持动态 sql ...

  5. Linux和Windows数据同步

    正在做一个小项目,关于Linux和Windows数据同步,新知识很兴奋,比赛很有信心,加油吧少年 项目进行中:今晚实验室包宿开整.

  6. QuantLib 金融计算——基本组件之 Date 类

    目录 QuantLib 金融计算--基本组件之 Date 类 Date 对象的构造 一些常用的成员函数 一些常用的静态函数 为估值计算配置日期 如果未做特别说明,文中的程序都是 Python3 代码. ...

  7. vue-cli3预设preset记录

    这两天公司搭建新项目的时候发现vue-cli3有一个神奇的的东西:preset(预设).preset其实是你在create新vue项目的时候,生成的插件配置项预设,也就是你在项目中需要用到的插件安装成 ...

  8. 蓝桥杯-学霸的迷宫(BFS+记录操作)

     算法提高 学霸的迷宫   时间限制:1.0s   内存限制:256.0MB      问题描述 学霸抢走了大家的作业,班长为了帮同学们找回作业,决定去找学霸决斗.但学霸为了不要别人打扰,住在一个城堡 ...

  9. hibernate_boolean类型的处理

    xml方式,直接写就行,hibernate会直接帮你生成: javaBean代码片段: private boolean leaf; public boolean isLeaf() { return l ...

  10. PHP 删除 数组 指定成员

    1. unset删除某一个 特定成员 $arr[] = ; $arr[] = ; $arr[] = ; ]); var_dump($arr); array() { []=> ) []=> ...