观察者模式 —— 让你的对象知悉现况 电玩女神 2022-07-16 18:13 52阅读 0赞 # 观察者模式 —— 让你的对象知悉现况 # ### 现状 ### 你的团队刚刚签下合同,负责建立Weather公司的下一代气象站——Internet气象站 ### 需求 ### * 气象站必须建立在Weather公司专利申请的WeatherData对象上,WeatherData对象负责追踪目前的天气状况(温度、湿度、气压) * 你的团队要建立一个应用,有三种布告板,分别显示:目前的状况、气象统计、简单的预报,要求实时更新 * 这是一个可扩展的气象站,要公布一组API,让其他开发人员可以写出自己的气象布告板,并插入此应用中 [![1.png][]][1.png 1] ### 我们的工作 ### 建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况、气象统计、天气预报。并提供一组API,让其他开发人员可以写出自己的气象布告板。 ### Weather公司的WeatherData类 ### WeatherData { getTemperature(); // 返回最近的气象测量数据:温度 getHumidity(); // 返回最近的气象测量数据:湿度 getPressure(); // 返回最近的气象测量数据:气压 measurementsChanged(); // 一旦气象测量更新,此方法会被调用 } 我们的工作是实现measurementsChanged(),好让它更新目前状况、气象统计、天气预报这三个布告板 ## 根据目前已有的条件分析 ## * WeatherData具有getter方法,可以取得三个测量值:温度、湿度、气压 * 当新的测量数据备妥时,measurementsChanged()方法就会被调用 * 我们需要实现三个使用数据的布告板:目前状况布告板、气象统计布告板、天气预报布告板。一旦WeatherData有新的测量,布告板要实时更新 * 此系统必须可扩展,让其他开发人员建立定制的布告板,用户可以随心所欲地添加或删除任何布告板。 ### 一个错误的做法 ### public class WeatherData { // 实例变量声明 public void measurementsChanged() { float temp = getTemperature(); float humidity = getHumidity(); float pressure = getPressure(); currentConditionDisplay.update(temp, humidity, pressure); statisticsDisplay.update(temp, humidity, pressure); forecastDisplay.update(temp, humidity, pressure); } // 其他的WeatherData方法 } 这样做的坏处有: 1. 我们是针对具体实现编程,而非针对接口编程 2. 对于每个新的布告板,我们都得修改代码 3. 我们无法再运行时动态地增加(或删除)布告板 4. 我们尚未封装改变的部分 ## 认识观察者模式 ## ### 观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新 ### ### 生活中的例子 ### 1. 报社的业务是出版报纸 2. 向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸 3. 当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来 4. 只要报社还在运营,就会一直有人(或单位)向他们订阅报纸或取消订阅报纸 ### 出版者+订阅者=观察者模式 ### 在软件工程中,出版者改称为“主题”(Subject),订阅者改称为“观察者”(Observer)。 [![2.png][]][2.png 1] ### 类图 ### [![3.png][]][3.png 1] ### 松耦合的威力 ### 当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。 观察者模式提供了一种对象设计,让主题和观察者之间松耦合 1. 主题只知道观察者实现了某个接口(Observer),而不需要知道具体实现类 2. 任何时候我们都可以增加新的观察者、运行时可以用新的观察者取代现有观察者、可以删除某些观察者 3. 当有新类型的观察者出现时,主题的代码无需改变 4. 可以独立地复用主题或观察者 5. 改变主体或者观察者的一方,并不会影响另一方 ## 气象站问题——解决办法:采用观察者(Observer Pattern) ## ### 观察者模式:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新 ### [![4.png][]][4.png 1] ### 接口设计 ### public interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } public interface Observer { void update(float temp, float humidity, float pressure); } public interface DisplayElement { void display(); } ## Java内置的观察者模式 ## java.util包内包含了最基本的Observer接口与Observable类,Observer接口与Observable类使用上更方便,因为许多功能都已经事先准备好了。你甚至可以使用推(push)或拉(pull)的方式传送数据。 #### Java内置的观察者模式如何运作 #### 1. 实现观察者接口(java.util.Observer),然后调用Observable的addObserver()方法,即可成为观察者 2. 主题(扩展java.util.Obserable)先调用setChanged()方法,标记状态已改变的事实。然后调用notifyObservers()或者notifyObservers(Object arg) 3. 观察者通过update(Observable o, Object arg)接收通知 setChanged() { changed = true; } notifyObservers(Object arg) { if(changed) { for every observer on the list { call update(this, arg) } changed = false } } notifyObservers() { notifyObservers(null) } ### 运行结果: ### [![5.png][]][5.png 1] ### 设计原则 ### 1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起 在观察者模式中,会改变的是主题的状态,以及观察者的数目和类型。用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题。 2. 针对接口编程,而不是针对实现编程 主题与观察者都使用接口:观察者利用主题的接口向主题注册/取消注册等;主题利用观察者的接口通知观察者。好处:松耦合 3. 少用组合,多用继承 将List组合到Subject中 4. 为了交互对象之间的松耦合设计而努力 松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低 ## 要点 ## * 观察者模式定义了对象之间一对多的关系 * 主题(也就是可观察者)用一个共同的接口来更新观察者 * 观察者和可观察者之间用松耦合方式结合(loosecoupling),可观察者不知道观察者的细节,只知道观察者实现了观察者接口 * 使用此模式时,你可从被观察者处推(pull)或拉(pull)(拉在本文章中没有实现)数据(然而, 推的方式被认为更“正确”) * 有多个观察者时,不可以依赖特定的通知次序 * Java有多种观察者模式的实现,包括了通用的java.util.Observable * 要注意java.util.Observable实现上所带来的一些问题 * 如果有必要的话,可以实现自己的Observable,这并不难 * Swing大量使用观察者模式,许多GUI框架也是如此 GitHub地址:https://github.com/linpeiyou/design-patterns-java [1.png]: /images/20220709/e3b30b2196fb41b6994b257505146516.png [1.png 1]: https://github.com/linpeiyou/design-patterns-java/blob/master/observer/image/1.png [2.png]: https://github.com/linpeiyou/design-patterns-java/raw/master/observer/image/2.png [2.png 1]: https://github.com/linpeiyou/design-patterns-java/blob/master/observer/image/2.png [3.png]: https://github.com/linpeiyou/design-patterns-java/raw/master/observer/image/3.png [3.png 1]: https://github.com/linpeiyou/design-patterns-java/blob/master/observer/image/3.png [4.png]: https://github.com/linpeiyou/design-patterns-java/raw/master/observer/image/4.png [4.png 1]: https://github.com/linpeiyou/design-patterns-java/blob/master/observer/image/4.png [5.png]: https://github.com/linpeiyou/design-patterns-java/raw/master/observer/image/5.png [5.png 1]: https://github.com/linpeiyou/design-patterns-java/blob/master/observer/image/5.png
相关 观察者——对象行为模式 意图 又被称为发布-订阅Subscribe模式、模型-视图View模式、源-收听者Listener模式或从属者模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象 £神魔★判官ぃ/ 2022年08月04日 11:52/ 0 赞/ 190 阅读
相关 观察者模式 观察者模式 Observer 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态上发生变化时,会通知所有观察者对 梦里梦外;/ 2022年08月03日 08:20/ 0 赞/ 67 阅读
相关 观察者模式 什么是观察者模式 有人这么说 > 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 > > 这个主题对象在状态上发生变化时,会通知所有观 梦里梦外;/ 2022年07月20日 12:05/ 0 赞/ 320 阅读
相关 观察者模式 —— 让你的对象知悉现况 观察者模式 —— 让你的对象知悉现况 现状 你的团队刚刚签下合同,负责建立Weather公司的下一代气象站——Internet气象站 需求 气象站必须 电玩女神/ 2022年07月16日 18:13/ 0 赞/ 53 阅读
相关 观察者模式 场景描述: 一个气象站应用,可以实时获取温度、湿度和气压信息,气象站提供一个封装好的类WeatherData,该类有最新的气象信息,当这些信息发生变动的时候,类中的meas 叁歲伎倆/ 2022年06月14日 10:24/ 0 赞/ 215 阅读
相关 观察者模式 观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 观察者模式图: ![输入图片说明][13105107_Mf 旧城等待,/ 2022年06月03日 02:41/ 0 赞/ 315 阅读
相关 观察者模式 什么是观察者模式? 简单的来说,观察者模式=出版者+订阅者。用比较书面的话来说的话是:定义了对象之间的一对多依赖,当一所对应的对象状态改变时,它的所有依赖者都会收到通知并 你的名字/ 2022年02月01日 13:53/ 0 赞/ 440 阅读
相关 观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 意图:定义对象 系统管理员/ 2021年09月17日 01:36/ 0 赞/ 533 阅读
相关 观察者模式 对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 ... 小灰灰/ 2020年06月13日 05:42/ 0 赞/ 629 阅读
还没有评论,来说两句吧...