JAVA语言设计模式之观察者模式实例讲解
小标 2018-12-04 来源 : 阅读 1197 评论 0

摘要:本文主要向大家介绍了JAVA语言设计模式之观察者模式实例讲解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言设计模式之观察者模式实例讲解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。


 

1. 引出问题


假设我们现在需要做一个实时天气预报的功能,并可以自定义任意多个显示界面。我们可以通过一个WeatherData的java类获取想要的信息,并将获取的相应信息分别显示在不同的界面。WeatherData的功能如下:

类名获取温度方法获取湿度方法获取气压方法通知更新方法
WeatherDatagetTempturegetHumiditygetPressuremeasurementsChanged


表中getXXX方法可以获取相应的信息,当天气发生变化时,measurementsChanges方法会被主动调用。


实现方案一:


public class WeatherData {

     

    //略去实例变量声明

     

    public void measurementsChanged() {

        float temp = getTempture();

        float humidity = getHumidity();

        float pressure = getPressure();

         

        //当前天气显示界面

        currentConditionsDisplay.update(temp,humidity,pressure);

         

        //数据分析建议界面

        statisticsDisplay.update(temp,humidity,pressure);

         

        //预报界面

        forecastDisplay.update(temp,humidity,pressure);

    }

     

    //略去WeatherData的其他方法

}

   


根据之前提到的条件,天气发生变化时,measurementsChanged方法会被主动调用,我们直接在measurementsChanged方法里更新各个显示界面。


以上实现方法会遇到几个问题:


(1)当我们需要自定义新的显示界面时,就必须要修改WeatherDate类。


(2)根据策略模式中我们学到的知识,以上代码针对的是具体实现编程而不是接口,回想一下从策略模式学到的原则和概念。


(3)我们无法在运行时动态地增加或是删除指定的显示界面。


(4)我们破坏了WeatherData类的封装。


所以,实际开发中应该避免以上代码的使用。观察者模式正好解决了这部分问题。


2. 观察者模式


2.1 定义


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


观察者模式中,被观察者,也可以说是被监听者称为主题,监听者称为观察者。如上情景中,WeatherData就是主题,而各种显示界面就是观察者。主题和观察者定义了一对多的。观察者依赖于此主题,只要主题状态一有变化,观察者就会被通知并更新自己的状态。


2.2 观察者模式类图



**UML图片使用的是ProcessOn绘制


2.3松耦合


当两个对象之间松耦合,他们仍然可以交互,但是不太清楚彼此的细节。观察者模式提供一种对象设计,让主题和观察者之间松耦合。


关于观察者的一切,主题只知道观察者实现了某个接口。主题不需要知道观察者的具体类是谁,有什么功能或者任何其他细节。


无论在什么时候观察者的增加,移除都不会对主题对象造成影响。这样我们就可以独立的复用主题或者观察者。如果我们在其他地方需要使用主题或者观察者,可以轻易的复用,因为二者并非时紧耦合的。


由此我们介绍一个新的设计原则:


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


松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。


3 解决问题


好了,我们开始设计天气预报以及显示的功能,在此之前,先看一下下面的设计图吧。



大家可以对照上面的设计图自己试着先写写代码。


首先,创建出两个接口,分别表示主题和观察者,主题接口如下:


public interface Subject {

    public void registerObserver(Observer o);

    public void unregisterObserver(Observer o);

     

    public void notifyObservers();

}

   


观察者接口如下:


public interface Observer {

    public void update(float tempture,float humidity,float pressure);

}

   


显示接口:


public interface DisplayElement {

    public void display();

}

   


以上3个接口分别对应设计图上面三个interface。


然后我们需要实现主题接口,由于我们需要从WeatherData获取数据并显示在显示屏上,所以WeatherData是实现了主题接口的具体类:


package org.canvas.doit;

 

import java.util.ArrayList;

import java.util.List;

 

public class WeatherData implements Subject {

     

    private List<observer> mObservers;

    private float tempture;

    private float humidity;

    private float pressure;

     

    public WeatherData() {

        // TODO Auto-generated constructor stub

        mObservers = new ArrayList<>();

    }

     

    @Override

    public void registerObserver(Observer o) {

        // TODO Auto-generated method stub

        if (o != null) {

            mObservers.add(o);

        }

    }

 

    @Override

    public void unregisterObserver(Observer o) {

        // TODO Auto-generated method stub

        if (o != null) {

            int index = mObservers.indexOf(o);

            if (index >=0) {

                mObservers.remove(o);

            }

        }

    }

 

    @Override

    public void notifyObservers() {

        // TODO Auto-generated method stub

        for(Observer observer : mObservers) {

            observer.update(tempture, humidity, pressure);

        }

    }

 

    public void measurementsChanged() {

        notifyObservers();

    }

     

    //此方法方便我们在测试过程中改变信息数值

    public void setMeasurements(float tempture,float humidity,float pressure) {

        this.tempture = tempture;

        this.humidity = humidity;

        this.pressure = pressure;

         

        measurementsChanged();

    }

 

    public float getTempture() {

        return tempture;

    }

 

    public float getHumidity() {

        return humidity;

    }

 

    public float getPressure() {

        return pressure;

    }

}

</observer>

   


WeatherData类实现了Subject接口,并使用List存储了所有观察者。setMeasurements函数只是方便我们后期测试,这里不是具体实现去网络上拉数据,有兴趣可以自己试着从网上拉取气象数据之后显示,有很多免费的api接口可以调用。


现在又了具体的主题类,下面我们就来设计一些具体的观察者类。


从设计上看,我们有三个观察这类,当前观测值的观察者类:


package org.canvas.doit;

 

public class CurrentConditionsDisplay implements Observer,DisplayElement {

    private float tempture;

    private float humidity;

    private Subject weatherData;

     

    public CurrentConditionsDisplay(Subject subject) {

        // TODO Auto-generated constructor stub

        this.weatherData = subject;

        weatherData.registerObserver(this);

    }

     

    @Override

    public void display() {

        // TODO Auto-generated method stub

        System.out.println("Current conditions : "+tempture+" F degrees and "+humidity+"% humitidy");

    }

 

    @Override

    public void update(float tempture, float humidity, float pressure) {

    &n    

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved