前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >这就是观察者模式

这就是观察者模式

作者头像
技术小黑屋
发布于 2018-09-05 01:37:41
发布于 2018-09-05 01:37:41
8680
举报
文章被收录于专栏:技术小黑屋技术小黑屋

观察者模式是软件设计模式中的一种,使用也比较普遍,尤其是在GUI编程中。关于设计模式的文章,网络上写的都比较多,而且很多文章写的也不错,虽然说有一种重复早轮子的嫌疑,但此轮子非彼轮子,侧重点不同,思路也不同,讲述方式也不近相同。

定义

关于定义,最准确的莫过于Head First设计模式中写到的。

观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监听一个主题对象。这样一来,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。

关键要素

主题

主题是观察者观察的对象,一个主题必须具备下面三个特征。

  • 持有监听的观察者的引用
  • 支持增加和删除观察者
  • 主题状态改变,通知观察者

观察者

当主题发生变化,收到通知进行具体的处理是观察者必须具备的特征。

为什么要用这种模式

这里举一个例子来说明,牛奶送奶站就是主题,订奶客户为监听者,客户从送奶站订阅牛奶后,会每天收到牛奶。如果客户不想订阅了,可以取消,以后就不会收到牛奶。

松耦合

  • 观察者增加或删除无需修改主题的代码,只需调用主题对应的增加或者删除的方法即可。
  • 主题只负责通知观察者,但无需了解观察者如何处理通知。举个例子,送奶站只负责送递牛奶,不关心客户是喝掉还是洗脸。
  • 观察者只需等待主题通知,无需观察主题相关的细节。还是那个例子,客户只需关心送奶站送到牛奶,不关心牛奶由哪个快递人员,使用何种交通工具送达。

通知不错过

由于被动接受,正常情况下不会错过主题的改变通知。而主动获取的话,由于时机选取问题,可能导致错过某些状态。

Java实现

Java中有观察者模式使用的API

  • java.util.Observable 这是一个类,而非接口,主题需要继承这个类。
  • java.util.Observer 这是一个接口,监听者需要实现这个接口。

示例代码

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

import java.util.Observable; import java.util.Observer; public class MainRoot { public static void main(String[] args) { Observer consumer = new Consumer(); MilkProvider provider = new MilkProvider(); provider.addObserver(consumer); provider.milkProduced(); } static class MilkProvider extends Observable { public void milkProduced() { setChanged();//状态改变,必须调用 notifyObservers(); } } static class Consumer implements Observer { @Override public void update(Observable arg0, Object arg1) { System.out.println("Consumer update..." + arg0 + ";arg1=" + arg1); } } }

上述代码完成了

  • 将consumer加入主题provider的观察者行列
  • provider设置状态变化,通知持有的观察者
  • 观察者consumer收到通知,打印日志处理

setChanged为何物

其实上述代码中存在这样一处代码setChanged();,如果在通知之前没有调用这个方法,观察者是收不到通知的,这是为什么呢

这里我们看一下setChanged的源码

1 2 3

protected synchronized void setChanged() { changed = true; }

很简单,然后找一下谁使用changed这个值

1 2 3

public synchronized boolean hasChanged() { return changed; }

notifyObservers的代码

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

public void notifyObservers(Object data) { int size = 0; Observer[] arrays = null; synchronized (this) { if (hasChanged()) { clearChanged(); size = observers.size(); arrays = new Observer[size]; observers.toArray(arrays); } } if (arrays != null) { for (Observer observer : arrays) { observer.update(this, data); } } }

但是为什么要加入这样一个开关呢?可能原因大致有三点

1.筛选有效通知,只有有效通知可以调用setChanged。比如,我的微信朋友圈一条状态,好友A点赞,后续该状态的点赞和评论并不是每条都通知A,只有A的好友触发的操作才会通知A。

2.便于撤销通知操作,在主题中,我们可以设置很多次setChanged,但是在最后由于某种原因需要取消通知,我们可以使用clearChanged轻松解决问题。

3.主动权控制,由于setChanged为protected,而notifyObservers方法为public,这就导致存在外部随意调用notifyObservers的可能,但是外部无法调用setChanged,因此真正的控制权应该在主题这里。

主动获取

观察者模式即所谓的推送方式,然而推送并非完美无缺。比如主题变化会推送大量的数据,而其中的一些观察者只需要某项数据,此时观察者就需要在具体实现中花费时间筛选数据。

这确实是个问题,想要解决也不难,需要主题为某些数据提供getter方法,观察者只需调用getter取数据处理即可。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

static class MilkProvider extends Observable { public void milkProduced() { setChanged();//状态改变,必须调用 notifyObservers(); } public float getPrice() { return 2.5f; } } static class Consumer implements Observer { @Override public void update(Observable arg0, Object arg1) { MilkProvider provider = (MilkProvider)arg0; System.out.println("milk price =" + provider.getPrice()); } }

不足与隐患

主要的问题表现在内存管理上,主要由以下两点

  • 主题持有观察者的引用,如果未正常处理从主题中删除观察者,会导致观察者无法被回收。
  • 如果观察者具体实现代码有问题,会导致主题和观察者对象形成循环引用,在某些采用引用计数的垃圾回收器可能导致无法回收。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【设计模式】观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
观察者模式 : 定义了 对象之间 一对多 的 依赖 , 令 多个 观察者 对象 同时 监听 某一个 主题对象 , 当 主题对象 发生改变时 , 所有的 观察者 都会 收到通知 并更新 ;
韩曙亮
2023/03/29
5130
【设计模式】观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
观察者模式浅析
观察者模式是一种对象行为型模式,其意图是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象都得到通知并被自动更新。观察者模式也叫发布-订阅模式(Publish-Subscribe)
孟君
2019/09/03
4330
观察者模式浅析
观察者模式是非常常用的设计模式_实现一个观察者模式
好久没有写博客啦,之前看完了《设计模式之禅》也没有总结一下,现在回忆一下设计模式之观察者模式。
全栈程序员站长
2022/09/20
2310
观察者模式是非常常用的设计模式_实现一个观察者模式
设计模式之观察者模式(二)
上一篇的观察者模式学习的还好吗?首先简单来回顾下上篇内容,有一个气象站的需求,需要在温度、湿度、气压改变的时候,实时更新三个布告板,以便能及时、准确的获取信息。所以,在设计模式的层面,我们最容易想到并且最正确的方式就是使用观察者模式来处理这个问题。
程序员小跃
2019/12/25
4590
设计模式走一遍---观察者模式(下)
上篇我们讲解了观察者模式的一些知识,而且自定义观察者模式的经典代码,(传送们:设计模式走一遍---观察者模式)
帅地
2018/10/09
2630
Android 设计模式之观察者模式
AntDream
2024/06/13
1290
Android 设计模式之观察者模式
Java设计模式(十五)----观察者模式
观察者模式 一、定义 二、结构 具体案例 推模型和拉模型 三、Java提供的对观察者模式的支持 Observer接口 Observable类 一、定义 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,
汤高
2018/01/11
8270
Java设计模式(十五)----观察者模式
观察者模式——心有灵犀
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
100000860378
2018/09/13
3330
使用JDK的观察者接口进行消息推送 顶
观察者模式就是对对象内部的变化进行观察,当发生改变时做出相应的响应。代码样例见 设计模式整理 !
算法之名
2019/08/20
4920
设计模式--观察者模式
  测量数据更新时需时时通知给第三方 需要设计开放型API,便于其他第三方公司也能接入气象站获取数据
HUC思梦
2020/09/03
2850
设计模式--观察者模式
【设计模式 10】观察者模式
观察者模式又叫发布订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时会通知所有观察者对象,使它们能够自动更新自己。
JuneBao
2022/10/26
2920
【设计模式 10】观察者模式
【设计模式-观察者模式】
【导读】队列中有一种模式是发布/订阅模式,订阅者可以有多个,当发布者发布了消息的时候,订阅者会收到通知,这就是观察者模式,也可以理解为生产者/消费者。
Liusy
2020/09/01
5900
【设计模式-观察者模式】
016.观察者模式
李斯和韩非子都是荀子的学生,李斯是师兄,韩非子是师弟,若干年后,李斯成为秦国的上尉,致力于统一全国,于是安插了间谍到各个国家的重要人物的身边进行监视,韩非子身边也有很多间谍,韩非子早饭吃的什么,晚上在做什么娱乐,李斯都了如指掌,我们先通过程序把这个过程展现一下,看看李斯是怎么监控韩非子的,先看类图:
CoderJed
2021/01/05
2790
016.观察者模式
设计模式:观察者模式
观察者模式属于行为型设计模式,用于建立对象间的一对多依赖关系。当主题(Subject)状态变化时,所有依赖的观察者(Observer)会自动收到通知并更新。
用户11531739
2025/03/11
630
五分钟学会观察者模式
观察者模式:多个观察者同时监听一个主题对象,当主题对象发生改变时,它的所有观察者都会收到通知。
Java识堂
2020/03/25
3810
五分钟学会观察者模式
观察者模式详解
从字面意思上去理解,所谓的观察者模式,首先有观察者(一个或者多个),被观察者(一个)。当被观察者状态发生变化的时候,就会去通知它的所有的观察者,然后由观察者根据被观察者的情况作出反应。观察者模式属于行为型模式。
开发者
2019/12/26
4150
观察者模式详解
设计模式之观察者模式
  随着工作时间的越来越长,发现对设计模式缺失的坏处越来越明显,但是当你知道某种设计模式的实现方式以后,你会发现,其实工作中早已经玩过这些东西,但是你之前并不知道它属于设计模式的一种,今天就先介绍一种设计模式:观察者模式,然后我们也手动实现观察者模式以加深印象。
阿豪聊干货
2018/08/09
2310
设计模式之观察者模式
设计模式之观察者模式
观察者模式(Observer Pattern)隶属于设计模式中的行为型模式。通过发布事件来将状态变化与处理逻辑解耦开来,可以拥有更好的可扩展性和可维护性。
Dylan Liu
2019/09/12
5340
观察者模式 : 一支穿云箭,千军万马来相见
本文介绍了观察者模式在 Android 中的使用,通过一个具体示例,展示了如何使用观察者模式在 Android 实现一对多的依赖关系,并总结了观察者模式的实现要点和注意事项。
张拭心 shixinzhang
2018/01/05
7500
观察者模式 : 一支穿云箭,千军万马来相见
利用Java提供的Observer接口和Observable类实现观察者模式
对于观察者模式,其实Java已经为我们提供了已有的接口和类。对于订阅者(Subscribe,观察者)Java为我们提供了一个接口,JDK源码如下: 1 package java.util; 2 3 public interface Observer { 4 void update(Observable o, Object arg); 5 } 和我们上一篇实现的观察者一样,仅提供一个update方法用于接收通知者的通知做出相应改变。 我们再来看看Java为我们提供了一个怎样的通知者(Publish,
用户1148394
2018/01/09
1.6K0
相关推荐
【设计模式】观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文