Java观察者模式的深入了解

 更新时间:2022年01月05日 15:48:15   作者:空山新雨后~  
这篇文章主要为大家介绍了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
 */

这种好处是我们如果有新的网站的加入,那么直接添加一个观察者类即可,不用修改代码

以及删除,注册都是独立开来的。 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • Java Hibernate中的多种查询方式及示例

    Java Hibernate中的多种查询方式及示例

    Hibernate提供了多种查询方式,包括HQL查询、SQL查询、QBC查询和Criteria查询等。HQL查询是基于面向对象的查询语言,可以方便地进行对象导航和多表查询;SQL查询允许用户直接使用SQL语句进行查询;QBC查询是基于Criteria的查询,具有类型安全和可重用性的优势
    2023-04-04
  • Java HashMap两种简便排序方法解析

    Java HashMap两种简便排序方法解析

    这篇文章主要介绍了Java HashMap两种简便排序方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • SpringBoot Security从入门到实战示例教程

    SpringBoot Security从入门到实战示例教程

    Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架,接下来通过本文给大家介绍SpringBoot Security从入门到实战示例教程,感兴趣的朋友一起看看吧
    2022-05-05
  • Java反射使用的详细介绍(最新推荐)

    Java反射使用的详细介绍(最新推荐)

    这篇文章主要介绍了Java反射使用的详细介绍,反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分,本文结合实例代码详细讲解,需要的朋友可以参考下
    2023-02-02
  • SpringBoot添加License的多种方式

    SpringBoot添加License的多种方式

    License指的是版权许可证,当我们开发完系统后,如果不想让用户一直白嫖使用,比如说按时间续费,License的作用就有了。我们可以给系统指定License的有效期,控制系统的可用时间。
    2021-06-06
  • 编写Spring MVC控制器的14个技巧(小结)

    编写Spring MVC控制器的14个技巧(小结)

    这篇文章主要介绍了编写Spring MVC控制器的14个技巧,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Spring Boot+maven打war包的方法

    Spring Boot+maven打war包的方法

    这篇文章主要介绍了Spring Boot+maven打war包的方法,本文通过实例代码相结合的形式给大家介绍的非常详细,需要的朋友参考下吧
    2018-05-05
  • Spring Boot 把配置文件和日志文件放到jar外部

    Spring Boot 把配置文件和日志文件放到jar外部

    如果不想使用默认的application.properties,而想将属性文件放到jar包外面,怎么做呢?下面小编给大家带来了两种方法解决Spring Boot 把配置文件和日志文件放到jar外部问题,感兴趣的朋友一起看看吧
    2018-02-02
  • shiro多验证登录代码实例及问题解决

    shiro多验证登录代码实例及问题解决

    这篇文章主要介绍了shiro多验证登录代码实例及问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java 动态模拟操作系统进程调度算法

    Java 动态模拟操作系统进程调度算法

    这篇文章主要介绍了采用java语言编程模拟N个进程采用动态高优先权优先进程调度算法。文中代码具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2021-12-12

最新评论