设计模式之观察者模式(Java)

问题引出

气象站项目
接到一个气象站的合同
可以监测到湿度温度这些变化
做一个开放接口 让第三方接入
现有接口:提供温度,气压和湿度的接口
目标:测量数据更新时需实时通知给第三方

WeatherData类
在这里插入图片描述

先写代码不使用观察者模式

在这里插入图片描述

package com.weatherstation.mark;

public class WeatherTest {
    public static void main(String[] args) {
        CurrentWeatherBoard currentWeatherBoard;
        WeatherStation weatherStation;
        currentWeatherBoard=new CurrentWeatherBoard();
        weatherStation=new WeatherStation(currentWeatherBoard);
        weatherStation.setData(28,160,30);
    }
}
package com.weatherstation.mark;

public class CurrentWeatherBoard {
    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;

    public void update(float currentTemperature,float currentPressure,float currentHumidity){
        this.currentTemperature=currentTemperature;
        this.currentPressure=currentPressure;
        this.currentHumidity=currentHumidity;
        display();

    }
    public void display(){

            System.out.println("Now currentTemperature:"+currentTemperature);
            System.out.println("Now currentPressure:"+currentPressure);
            System.out.println("Now currentHumidity:"+currentHumidity);

    }
}

package com.weatherstation.mark;

public class WeatherStation {

    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;

    private CurrentWeatherBoard currentWeather;

    public float getCurrentTemperature() {
        return currentTemperature;
    }

    public float getCurrentPressure() {
        return currentPressure;
    }

    public float getCurrentHumidity() {
        return currentHumidity;
    }

    public WeatherStation(CurrentWeatherBoard currentWeather){
        this.currentWeather=currentWeather;
    }
    public void update(float tempTemperature,float tempPressure,float tempHumidity){
        this.currentTemperature=currentTemperature;
        this.currentPressure=currentPressure;
        this.currentHumidity=currentHumidity;
    }
    //增加公告板 code需要改变
    public void dataChange(){
        currentWeather.update(getCurrentTemperature(),getCurrentPressure(),getCurrentHumidity());
    }
    public void setData(float tempTemperature,float tempPressure,float tempHumidity){
        this.currentTemperature=tempTemperature;
        this.currentPressure=tempPressure;
        this.currentHumidity=tempHumidity;
        dataChange();
    }
}

问题如果新加公告栏 需要改变代码 扩展性不好

怎么解决 思考问题

观察者模式原理
订报业务
1.报社 Subject
2.用户 Observer

2.Subject 注册 移除 通知

在这里插入图片描述

3.Observer :接收输入
在这里插入图片描述
定义:
对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化

观察者模式实现

类图
在这里插入图片描述
接口定义:

package com.mode.weatherstation.mark;
//气象站 当做订阅的主题接口
public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
}

package com.mode.weatherstation.mark;

public interface Observer {
    public void update(float currentTemperature,float currentPressure,float currentHumidity);
}

观察者类:

package com.mode.weatherstation.mark;

public class StaticWeatherBoard implements Observer
{
    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;

    private float aveValue;
    public void update(float currentTemperature,float currentPressure,float currentHumidity){
        aveValue=(currentTemperature+currentPressure+currentHumidity)/3;
        display();

    }
    public void display(){

        System.out.println("Ave Value:"+aveValue);

    }
}


package com.mode.weatherstation.mark;

public class CurrentWeatherBoard implements Observer{
    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;

    public void update(float currentTemperature,float currentPressure,float currentHumidity){
        this.currentTemperature=currentTemperature;
        this.currentPressure=currentPressure;
        this.currentHumidity=currentHumidity;
        display();

    }
    public void display(){

            System.out.println("Now currentTemperature:"+currentTemperature);
            System.out.println("Now currentPressure:"+currentPressure);
            System.out.println("Now currentHumidity:"+currentHumidity);

    }
}

订阅类(主题类):

package com.mode.weatherstation.mark;

import com.weatherstation.mark.CurrentWeatherBoard;

import java.util.ArrayList;

public class WeatherStation implements Subject{

    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;

    private ArrayList<Observer> observers;

    public float getCurrentTemperature() {
        return currentTemperature;
    }

    public float getCurrentPressure() {
        return currentPressure;
    }

    public float getCurrentHumidity() {
        return currentHumidity;
    }

    public WeatherStation(){
        observers=new ArrayList<Observer>();
    }
    public void update(float tempTemperature,float tempPressure,float tempHumidity){
        this.currentTemperature=currentTemperature;
        this.currentPressure=currentPressure;
        this.currentHumidity=currentHumidity;
    }
    //增加公告板 code需要改变
    public void dataChange(){
        notifyObservers();
     }
    public void setData(float tempTemperature,float tempPressure,float tempHumidity){
        this.currentTemperature=tempTemperature;
        this.currentPressure=tempPressure;
        this.currentHumidity=tempHumidity;
        dataChange();
    }

    @Override
    public void registerObserver(Observer o) {
    observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        if(observers.contains(o))
        {
         observers.remove(o);
        }
    }

    @Override
    public void notifyObservers() {
        for (Observer o:observers){
            o.update(getCurrentTemperature(),getCurrentPressure(),getCurrentHumidity());
        }
    }
}

测试类:

package com.mode.weatherstation.mark;

public class WeatherTest {
    public static void main(String[] args) {
        CurrentWeatherBoard currentWeatherBoard;
        StaticWeatherBoard staticWeatherData;
        WeatherStation weatherStation;

        weatherStation=new WeatherStation();
        currentWeatherBoard=new CurrentWeatherBoard();
        staticWeatherData=new StaticWeatherBoard();

        weatherStation.registerObserver(currentWeatherBoard);
        weatherStation.registerObserver(staticWeatherData);
        weatherStation.setData(35,120,38);

        System.out.println();
        System.out.println();
        System.out.println();
        weatherStation.removeObserver(staticWeatherData);
        weatherStation.setData(25,150,50);

    }
}

接口定义 一对多
不用修改代码,重启服务

Java 内置观察者(JDK9 已经弃用)

Observable 订阅者 主题 是一个类
Observer 观察者 是一个接口

package com.javainner.weathersatation.mark;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
//是一个类 所以不能多重继承
public class WeatherStation extends Observable {


    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;

    private ArrayList<Observer> observers;

    public float getCurrentTemperature() {
        return currentTemperature;
    }

    public float getCurrentPressure() {
        return currentPressure;
    }

    public float getCurrentHumidity() {
        return currentHumidity;
    }

    public WeatherStation(){
        observers=new ArrayList<Observer>();
    }
    public void update(float tempTemperature,float tempPressure,float tempHumidity){
        this.currentTemperature=currentTemperature;
        this.currentPressure=currentPressure;
        this.currentHumidity=currentHumidity;
    }
    //需要注意  java 内置观察者 需要调用setChanged方法
    public void dataChange(){
        setChanged();
        notifyObservers(new Data(getCurrentTemperature(),getCurrentPressure(),getCurrentHumidity()));
     }


    public void setData(float tempTemperature, float tempPressure, float tempHumidity){
        this.currentTemperature=tempTemperature;
        this.currentPressure=tempPressure;
        this.currentHumidity=tempHumidity;
        dataChange();
    }
    //载体类,放更新数据
    public class Data{

        private float currentTemperature;
        private float currentPressure;
        private float currentHumidity;

        public Data(float currentTemperature, float currentPressure, float currentHumidity) {
            this.currentTemperature = currentTemperature;
            this.currentPressure = currentPressure;
            this.currentHumidity = currentHumidity;
        }

        public float getCurrentTemperature() {
            return currentTemperature;
        }



        public float getCurrentPressure() {
            return currentPressure;
        }



        public float getCurrentHumidity() {
            return currentHumidity;
        }


    }
}

package com.javainner.weathersatation.mark;

import java.util.Observable;
import java.util.Observer;


public class CurrentWeatherBoard implements Observer {
    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;


    public void display(){

            System.out.println("Now currentTemperature:"+currentTemperature);
            System.out.println("Now currentPressure:"+currentPressure);
            System.out.println("Now currentHumidity:"+currentHumidity);

    }

    @Override
    public void update(Observable o, Object arg) {
            this.currentTemperature=((WeatherStation.Data)arg).getCurrentTemperature();
            this.currentPressure=((WeatherStation.Data)arg).getCurrentTemperature();
            this.currentHumidity=((WeatherStation.Data)arg).getCurrentPressure();
            display();


    }
}

package com.javainner.weathersatation.mark;

import java.util.Observable;
import java.util.Observer;

public class StaticWeatherBoard implements Observer
{
    private float currentTemperature;
    private float currentPressure;
    private float currentHumidity;

    private float aveValue;

    public void display(){

        System.out.println("Ave Value:"+aveValue);

    }

    @Override
    public void update(Observable o, Object arg) {
        aveValue=aveValue=(((WeatherStation.Data)arg).getCurrentTemperature()+((WeatherStation.Data)arg).getCurrentTemperature()+((WeatherStation.Data)arg).getCurrentPressure())/3;
        display();
    }
}

package com.javainner.weathersatation.mark;

public class WeatherTest {
    public static void main(String[] args) {
        CurrentWeatherBoard currentWeatherBoard;
        StaticWeatherBoard staticWeatherData;
        WeatherStation weatherStation;

        weatherStation=new WeatherStation();
        currentWeatherBoard=new CurrentWeatherBoard();
        staticWeatherData=new StaticWeatherBoard();

        //执行顺序 最后注册的先执行代码
        weatherStation.addObserver(currentWeatherBoard);
        weatherStation.addObserver(staticWeatherData);
        weatherStation.setData(35,120,38);

        System.out.println();
        System.out.println();
        System.out.println();
        weatherStation.deleteObserver(staticWeatherData);
        weatherStation.setData(25,150,50);

    }
}

观察者模式关键点

生活上订报 订牛奶
解决问题:类或者对象之间存在一对多的依赖关系
1 subject 主题者 通知 推送信息 拉信息(提取信息)
多 observer 观察者
松耦合 主题者和观察者之间的关系
Java内置观察者 推和拉都实现了

设计原则体现

原则1
找出程序中会变化的方面,然后将其和固定不变的方面相分离
体现:
在观察者模式中,会改变的是主题的状态。以及观察者的数目和类型。用这个模式,你可以改变依赖该主题状态对象。却不必改变主题。这就叫提前规划

原则2
针对接口编程,不针对实现编程
体现:
主题与观察者都使用接口:观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运作正常。又同事具有松耦合的优点

原则3
多用组合,少用继承
体现:
观察者模式利用”组合“将许多观察者组合进主题中。对象之间的这种关系不是通过继承产生的。而是在运行时利用组合的方式而产生的。

注:如果文章有任何错误或不足,请各位大佬尽情指出,评论留言留下您宝贵的建议!如果这篇文章对你有些许帮助,希望可爱亲切的您点个赞推荐一手,非常感谢啦
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值