观察者模式学习笔记(详细)

一、什么是观察者模式

观察者模式,是定义对象之间的一对多的关系,主要作用是减少对象之间的耦合度,分为两个角色

  1. 被观察者:其实就是发布者,发布消息通知所有的观察者
  2. 观察者:接到被观察者发布的消息做出相应的动作


上图中,左边一组是被观察者,右边一组是观察者

  • Subjecct:被观察者抽象类,拥有类成员ObserverList,和三个抽象方法
    ObserverList:存放所有的观察者对象
    addObserver():向ObserverList中添加观察者对象
    delObject():从ObserverList中删除观察者对象
    notifyObservers():通知所有的观察者对象

  • SubjectItem:具体的被观察者类,继承Subject接口,有具体的动作方法,调用父类的notifyObject()方法通知所有的观察者

  • Observer:观察者接口,有一个抽象方法update(),供被观察者调用

  • ObserverItem:具体的观察者类,实现Observer类,实现update()方法

二、使用场景

游戏中,被观察者主角有所动作就通知观察者们
支付中,一个商品购买成功,需要执行许多操作(更新订单,发送邮件,更新账户…),这时就可以使用观察者模式来减少耦合
再比如,关注动态,动态更新,需要发送通知给所有的关注者

三、具体实现

简单的一个冒险游戏,勇者做为被观察者,观察者有怪物,食物,NPC
当勇者移动碰到怪物时血量减1,碰到食物时血量加1,碰到NPC时展开剧情

  1. 编写Observer接口
 public interface Observer {public void update();}
  1. 编写Subject抽象类
 public abstract class Subject {//观察者集合private List<Observer> observerList = new ArrayList<>();//添加观察者public void addObserver(Observer observer){observerList.add(observer);}//删除观察者public void delObserver(Observer observer){observerList.remove(observer);}//通知所有观察者public void notifyObservers(){for(Observer observer : observerList){observer.update();}}}

observerList集合存放了观察者接口,不直接存放观察者类
notifyObservers()方法遍历observerList集合,调用update()方法
通过抽象层减少耦合

  1. 编写勇者类(被观察者)
     public class Hero extends Subject {static int X = 0;static int Y = 0;//勇者移动public void move(int x, int y){X = x;Y = y;super.notifyObservers();}}

Hero类有move()方法,让勇者移动并调用父类的notifyObservers()方法通知所有的观察者

  1. 编写怪物类(观察者)
 public class Monster implements Observer {static int X = 5;static int Y = 7;@Overridepublic void update() {if(Hero.X == X && Hero.Y == Y){System.out.println("怪物攻击勇者!");}}}

Monster类实现Observer接口,实现具体的update()方法

  1. 编写食物类(观察者)
 public class Food implements Observer {static int X = 8;static int Y = 8;@Overridepublic void update() {if(Hero.X == X && Hero.Y == Y){System.out.println("勇者吃到了食物,血量加1!");}}}

Food类实现Observer接口,实现具体的update()方法

  1. 编写npc类(观察者)
 public class Npc implements Observer {static int X = 15;static int Y = 20;@Overridepublic void update() {if(Hero.X == X && Hero.Y == Y){System.out.println("勇者遇到NPC,剧情展开!");}}}

Npc类实现Observer接口,实现具体的update()方法

  1. 编写执行类
 public class Run {public static void main(String[] args){//初始化对象Hero hero = new Hero();Monster monster = new Monster();Food food = new Food();Npc npc = new Npc();//添加观察者hero.addObserver(monster);hero.addObserver(food);hero.addObserver(npc);//勇者移动,遇到怪物hero.move(5,7);//勇者移动,吃到食物hero.move(8,8);//勇者移动,遇到npchero.move(15,20);}}

勇者移动时通知了所有已注册的观察者,执行各自的update方法

  1. 运行结果

四、总结

  • 优点:
    使用抽象的方式来减少被观察者和观察者之间的耦合,可以方便的增加观察者

  • 缺点:
    如果被观察者有过多的直接观察者和间接观察者的话,会花费更多的时间,如果观察者之间存在循环依赖的话,会导致他们直接进行循环调用,最终导致系统崩溃
    观察者可以知道被观察者发生的变化,但是无法知道被观察者是如何发生的变化

观察者模式学习笔记(详细)相关推荐

  1. HTML入门学习笔记+详细案例

    ✨HTML入门学习笔记+详细案例 作者介绍:

  2. CTFHUB http协议题目 学习笔记 详细步骤 请求方式 302跳转 cookie 基础认证 响应源代码

    CTFHUB http协议题目 学习笔记 详细步骤 请求方式 302跳转 cookie 基础认证 响应源代码 WEB-HTTP协议 1-请求方式 2-302跳转 3.cookie 4.基础认证 5.响 ...

  3. 设计模式之观察者模式学习笔记

    前言 观察者模式,又叫作发布-订阅模式.一般的特点为对象间的关系为一对多,当一个对象被修改的时候,就会通知它依赖的对象 定义 定义对象间一种一对多的依赖关系,每当一个对象状态发生改变时,所有依赖于它的 ...

  4. python入门学习笔记——详细基础知识篇(第10章 正则表达式(重点)与JSON)

    第10章 正则表达式(重点)与JSON 初识正则表达式 元字符与普通字符 字符集 概括字符集 数量词 贪婪与非贪婪 匹配0次1次或者无限多次 边界匹配符(^ .$) 组 匹配模式参数 re.sub正则 ...

  5. Linux线程互斥学习笔记--详细分析

    一.互斥锁 为啥要有互斥? 多个进程/线程执行的先后顺序不确定,何时切出CPU也不确定. 多个进程/线程访问变量的动作往往不是原子的. 1. 操作步骤 (1)创建锁 // 创建互斥锁mutex pth ...

  6. Scala学习笔记-详细记录学习中遇到的知识点

    目录 输入 print输出 变量 数据类型 标识符与关键字 运算符优先级 if else for循环 yield生成器 break与continue 函数 局部函数 惰性lazy 异常 类与对象 构造 ...

  7. malloc 源码_【C++学习笔记(九)】之 new运算符的使用/ new 与 malloc的异同(附代码,详细注释)...

    new 运算符的使用 一. new的简单介绍: new运算符用于在堆区开辟空间,所有new出来的对象,对返回该类对象的指针. 二. new 与 malloc 的异同点: 1.malloc作用相同, m ...

  8. Linux 学习笔记之超详细基础linux命令 Part 3

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 2----------------- ...

  9. JUC.Condition学习笔记[附详细源码解析]

    JUC.Condition学习笔记[附详细源码解析] 目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Conditi ...

最新文章

  1. SVO 学习笔记(深度滤波)
  2. FILE文件流的中fopen、fread、fseek、fclose的使用
  3. 抖音小程序微信小程序五角星型评分插件自定义分数组件
  4. 数据结构:最大子序列和
  5. 用计算机弹没那种命,成熟小女人QQ个性网名 没那种命就别犯那种病
  6. 第25天多线程、网络编程
  7. JAVA 网络编程小记
  8. InfluxDB(官方使用说明)
  9. cover-letter
  10. SAP License:SAP财务管理的认识
  11. Rust : 宏、重复、及向量与递归实例
  12. linux系统清空文件内容
  13. 用友U8案例教程财务报表
  14. Webservice 学习笔记
  15. 金山词霸PC企业版2016
  16. Composer加载的symfony/var-dumper类库 字体大小样式设置
  17. C语言switch语句无break
  18. 初中计算机数学,初中数学
  19. Fater RCNN 试着加入注意力机制模型
  20. 使用 Python 进行数据预处理的标准化

热门文章

  1. 如何对一个老系统进行梳理分析
  2. Python:恶搞,将你朋友照片做成熊猫人表情包
  3. Nginx反向代理问题
  4. map.json-1
  5. 记录一下DSFD源码中demo.py的debug过程
  6. 贵州省水系数据,水库数据,线要素和面要素
  7. matlab中值滤波法算法,基于MATLAB中值滤波算法的优化与实现
  8. 卷积神经网络详解 - 卷积层逻辑篇
  9. 判断回文字符串(C语言版指针实现)
  10. java 小程序之随机点名系统