Java观察者模式的深入了解
作者:空山新雨后~
一、观察者模式的定义和特点
观察者模式的定义:
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
特点:
1.降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
2.目标与观察者之间建立了一套触发机制。
二、观察者模式的结构
实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来,这违反了面向对象的设计原则。 观察者模式的主要角色如下。
Subject类:他把所有对观察者对象的引用保存在一个聚合里,每个主题都可以有任何数量的观察者,抽象主题提供一个接口,可以增加和删除任意的观察者对象
observer类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
ConcreteSubject:具体主题,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的的观察者发出通知
ConcreteObserver:具体观察者,实现抽象观察者角色所要求的的更新接口,以便使本身的状态与主题的状态向协调
三、代码实例
现在有一个需求,各网站需要订阅天气需求, 我们这边要及时更新并发送天气信息,且我们可以自由的注册或者移除想要发送的网站,用观察者模式实现。
如果我们用传统的模式实现该案例,那么会出现一个问题,就是如果我们要修改网站,那可能回去改动网站类的代码,和我们操作更新数据的代码,这不符合我们的开闭原则,因此我们采用观察者模式去实现,因为他也是一种一对多的依赖关系,生活中这种案例多不胜数,例如订阅杂志,等。
结构图如下
代码示例
抽象目标类Subject
package com.observerPattern.weatherCase;/** * @author wang * @version 1.0 * @packageName com.observerPattern.weatherCase * @className Subject * @date 2021/12/28 15:49 * @Description Subject抽象目标类,由具体的目标去实现 */public interface Subject package com.observerPattern.weatherCase; /** * @author wang * @version 1.0 * @packageName com.observerPattern.weatherCase * @className Subject * @date 2021/12/28 15:49 * @Description Subject抽象目标类,由具体的目标去实现 */ public interface Subject { /** * @Date 2021/12/28 16:20 * @Param * @param o * @Return void * @MetodName registerObserver * @Author wang * @Description 注册观察者方法 */ void registerObserver(Observer o); /** * @Date 2021/12/28 16:20 * @Param * @param o * @Return void * @MetodName removeObserver * @Author wang * @Description 移除观察者 */ void removeObserver(Observer o); /** * @Date 2021/12/28 16:20 * @Param * @Return void * @MetodName notifyObservers * @Author wang * @Description 通知观察者 */ void notifyObservers(); }
具体目标WeatherDate类
package com.observerPattern.weatherCase; import java.util.ArrayList; /** * @author wang * @version 1.0 * @packageName com.observerPattern.weatherCase * @className WeatherDate * @date 2021/12/28 16:00 * @Description 包含最新的天气数据,是具体的目标,实现了抽象目标subject * 该类含有观察者集合,使用ArrayLis集合管理. * 当数据有更新时,就主动的调用ArrayList集合通知各个观察者 * */ public class WeatherDate implements Subject{ private float temperature; private float pressure; private float humidity; private ArrayList<Observer> observers; /** * @Date 2021/12/28 16:10 * @Param * @Return null * @MetodName WeatherDate * @Author wang * @Description 初始化观察者集合 */ public WeatherDate() { this.observers = new ArrayList<Observer>(); } public float getTemperature() { return temperature; } public float getPressure() { return pressure; } public float getHumidity() { return humidity; } /** * @Date 2021/12/28 16:10 * @Param * @Return void * @MetodName dateChange * @Author wang * @Description 调用通知方法,将更新后的数据推送至各个观察者 */ public void dateChange() { notifyObservers(); } /** * @Date 2021/12/28 16:11 * @Param * @param temperature * @param pressure * @param humidity * @Return void * @MetodName setDate * @Author wang * @Description 更新数据 */ public void setDate(float temperature,float pressure,float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; dateChange(); } /** * @Date 2021/12/28 16:11 * @Param * @param o * @Return void * @MetodName registerObserver * @Author wang * @Description z注册一个观察者 */ @Override public void registerObserver(Observer o) { observers.add(o); } /** * @Date 2021/12/28 16:11 * @Param * @param o * @Return void * @MetodName removeObserver * @Author wang * @Description 移除一个观察者 */ @Override public void removeObserver(Observer o) { if(observers.contains(o)) { observers.remove(o); } } /** * @Date 2021/12/28 16:12 * @Param * @Return void * @MetodName notifyObservers * @Author wang * @Description 通知观察者 */ @Override public void notifyObservers() { for(int i = 0;i< observers.size();i++) { observers.get(i).update(this.temperature,this.pressure,this.humidity); } } }
抽象观察者Observer:
package com.observerPattern.weatherCase; /** * @author wang * @version 1.0 * @packageName com.observerPattern.weatherCase * @className Observer * @date 2021/12/28 15:50 * @Description 观察者接口,方法更新温度,压力,湿度,由具体的观察者实现 */ public interface Observer { /** * @Date 2021/12/28 16:18 * @Param * @param temperature * @param pressure * @param humidity * @Return void * @MetodName update * @Author wang * @Description */ void update(float temperature,float pressure,float humidity); }
具体观察者1
package com.observerPattern.weatherCase; /** * @author wang * @version 1.0 * @packageName com.observerPattern.weatherCase * @className CurrentCondition * @date 2021/12/28 15:54 * @Description 具体的一个观察者类,表示当前天气情况,实现观察者接口 */ public class CurrentCondition implements Observer{ private float temperature; private float pressure; private float humidity; /** * @Date 2021/12/28 15:58 * @Param * @param temperature * @param pressure * @param humidity * @Return void * @MetodName update * @Author wang * @Description该方法将更新后的数据推送至该观察者,观察者打印 */ @Override public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } /** * @Date 2021/12/28 15:59 * @Param * @Return void * @MetodName display * @Author wang * @Description 该方法显示更新的数据 */ public void display() { System.out.println("测试显示当前气温:" + temperature + "度"); System.out.println("测试显示当前压力:" + pressure + "帕"); System.out.println("测试显示当前湿度:" + humidity + "Rh"); } }
具体观察者2:
package com.observerPattern.weatherCase; /** * @author wang * @version 1.0 * @packageName com.observerPattern.weatherCase * @className SinaNet * @date 2021/12/28 16:21 * @Description 新浪网站作为一个观察者 */ public class SinaNet implements Observer{ private float temperature; private float pressure; private float humidity; /** * @Date 2021/12/28 15:58 * @Param * @param temperature * @param pressure * @param humidity * @Return void * @MetodName update * @Author wang * @Description该方法将更新后的数据推送至该观察者,观察者打印 */ @Override public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } /** * @Date 2021/12/28 15:59 * @Param * @Return void * @MetodName display * @Author wang * @Description 该方法显示更新的数据 */ public void display() { System.out.println("=======新浪网站======="); System.out.println("新浪显示当前气温:" + temperature + "度"); System.out.println("新浪显示当前压力:" + pressure + "帕"); System.out.println("新浪显示当前湿度:" + humidity + "Rh"); } }
客户端测试类
package com.observerPattern.weatherCase; /** * @author wang * @version 1.0 * @packageName com.observerPattern.weatherCase * @className ClientTest * @date 2021/12/28 16:12 * @Description 客户端测试代码,测试观察者模式 */ public class ClientTest { public static void main(String[] args) { //创建一个weatherDate具体目标 WeatherDate weatherDate = new WeatherDate(); //创建一个观察者 CurrentCondition currentCondition = new CurrentCondition(); //注册一个观察者 weatherDate.registerObserver(currentCondition); //注册新浪 SinaNet sinaNet = new SinaNet(); weatherDate.registerObserver(sinaNet); //测试更新 System.out.println("通知给各观察者"); weatherDate.setDate(3,65,12); //测试移除 weatherDate.removeObserver(currentCondition); System.out.println("========================"); System.out.println("第二次更新"); weatherDate.setDate(6,88,16); } } /* 通知给各观察者 测试显示当前气温:3.0度 测试显示当前压力:65.0帕 测试显示当前湿度:12.0Rh =======新浪网站======= 新浪显示当前气温:3.0度 新浪显示当前压力:65.0帕 新浪显示当前湿度:12.0Rh ======================== 第二次更新 =======新浪网站======= 新浪显示当前气温:6.0度 新浪显示当前压力:88.0帕 新浪显示当前湿度:16.0Rh */
这种好处是我们如果有新的网站的加入,那么直接添加一个观察者类即可,不用修改代码
以及删除,注册都是独立开来的。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!