写点什么

观察者模式详解

发布于: 2020 年 06 月 23 日
观察者模式详解

设计模式想必大家都懂一些,不仅能体现平时设计写代码的基本功,而且也是面试时的高频考点。今天来讲解学习下 「观察者模式」。 本文在讲解具体模式的同时,也会列举 jdk 以及 常用框架中使用到的地方,帮助大家加深理解。

设计模式的学习,我的建议是,首先弄懂它的含义,和前人已经总结沉淀下来的设计原则。将这些概念记在心里,当工作中碰见对应的需求开发工作时,按照原则去认真思考、设计实现,最终符合要求的结果往往就已经是一些设计模式的具体实现了。

场景举例

首先列出一个实战场景,用这个场景来讲述观察者模式是什么,以及为什么适用这个场景。

现在有一个气象观测站应用系统,主要包含三个部分,获取气象数据的物理装置(包括温度、湿度、密度等)、WeatherData(追踪气象站的数据并更新布告板)和布告板(显示看板给用户看)。

首先来看一个错误示例:

public class WeatherData {
// 实例变量声明
// 气象数据变化时更新对应的布告板
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
// 更新各种布告板
currentConditionDisplay.update(temp,humidity,pressure);
statsticConditionDisplay.update(temp,humidity,pressure);
}
}

首先各种布告板应该是一个统一的接口,其次更新布告板不能针对具体实现编程,这样会导致以后在增加或者删除布告板时必须修改程序。

结合设计原则思考

根据这个场景我们首先按照设计原则来思考:

  • 找出程序中变化的方面,然后将其和固定的部分分离。

场景中气象站观测的天气数据时变化的,布告板的数量和类型是变化的。

  • 针对接口编程,不针对实现编程。

这里主要指我们的布告板应该是一个接口,而天气对象 WeatherData 也应该是一个统一接口,后面还会介绍。

  • 多用组合,少用继承

这里布告板和天气对象之间的关系应该为天气对象组合布告板,这种关系不是通过继承来的,而是通过在运行时通过组合的方式产生的。

这个场景,我们能看到,只要天气对象有数据变更,就需要通知所有布告板,这是一个典型的主题-订阅模式,也就是我们今天要学习的观察者模式。

我们把 WeatherDta 对象当作主题,把布告板当做观察者,布告板为了获取信息,必须向 WeatherData 对象注册。

每个布告板都有差异,这也就是我们为什么需要一个共同的接口。尽管布告板的类不一样,但是它们应该实现相同的接口,好让 WeatherData 对象能够知道如何把观测值传给他们。

大师的设计

首先定义对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。正好对应我们举例中的 WeatherData 主题对象,当它改变时,所有的布告板收到状态变更通知,进行各自业务处理。

类图如下:

通过上面观察者模式的类图,我们可以看到两个对象之间是松耦合的,但他们之间依然可以交互,但是不太清楚彼此的细节。 观察者模式提供了这种对象设计,让主题和观察者之间松耦合。

「你可能要问为什么呢?」

关于观察者的一切,主题只知道观察者实现了某个接口(即 Observer 接口)。主题不需要知道观察者的具体类是谁,做了些什么以及任何细节。

任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现 Observer 接口的对象列表,所以可以随时增加观察者。

当有新类型观察者出现时,主题的代码不需要作任何修改。我们要做的就是在新的类里实现观察者接口,然后注册为观察者即可。主题不在乎别的,它只会发送通知给所有实现了观察者接口的注册对象。

改变主题或者观察者其中一方,并不会影响另一方。因为两者是松耦合的,所以只要他们之间的接口仍被遵守,我们就可以自由的改变他们。

所以这就总结出我们今天新学习的设计原则:

「为了交互对象之间的松耦合设计而努力。」

实际应用

  1. java中内置的观察者模式,java.util包内包含基本的Observer接口与Observable类,可以使用推(push)或拉(pull)的方式传数据。

  2. jdk 中 JavaBeans 里的观察者模式,具体查看 PropertyChangeListener 接口。

  3. 想一下我们平时用的消息队列,比如rocketMQ等,本质上也是运用了观察者模式的思想;

总结

观察者模式:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。



后面一篇内容,将会带来装饰着模式的讲解,敬请期待。



原创真心不易,希望你能帮我个小忙呗,如果本文内容你觉得有所收获,请帮忙点个“在看”呗,或者转发分享让更多的小伙伴看到。





发布于: 2020 年 06 月 23 日阅读数: 56
用户头像

专注于Java技术栈,热爱编程的你值得拥有 2018.03.21 加入

半路出家学习编程,脚踏实地,目前就职于某世界500强。现阶段坚持写作,分享知识,形成自己的体系。 从计划到坚持,再到形成自己的节奏。fighting

评论

发布
暂无评论
观察者模式详解