JAVA设计模式(2)- 观察者模式

1.Internet气象站项目:

   1.提供温度,气压和湿度的接口
   2.测量数据更新时需要时通知给第三方
   3.需要设计开放型API,便于其他公司的也能接入点气象站获取数据

2.WeatherDate类

   WeatherData
   
   getTemperature()
   getHumidity()
   getPressure()
   dataChange()     

3.气象站

  当气象站监测到这些数据的变化的时候,就通知dataChange()函数。

方案一:通用的设计方案

1.设计一个公告板

 CurrentConditions
  
     updata()
     display()

2.设计WeatherData类

   WeatherDate
  
   getTemperature()
   getHumidity()
   getPressure()
   dataChange()  
 当dataChange() 接收到信息的变化的时候,就通知公告板的update()去通知更新数据

代码实现:

WeatherData

package com.java.Internetweather_1;
//相当于一个接口
public class WeatherData {
        private float temperature;
        private float humidity;
        private float pressure;
        //有了公告板后,我们就可以把它当作一个属性,被接口使用
        private CurrentConditions currentConditions;
        
        public WeatherData(CurrentConditions currentConditions) {
                 this.currentConditions =  currentConditions; 
            
        }
        public float getTemperature() {
            return temperature;
        }
        public float getHumidity() {
            return humidity;
        }
        public float getPressure() {
            return pressure;
        }
       public void dataChange() {
         //当公告板有信息后,我们就调用它
         //temperature, pressure, humidity都是从气象站获取的,所以用get()方法,然后传给公告板的 
           currentConditions.updata(getTemperature(),getPressure(), getPressure());
       }
      //假设气象站有数据变化setData()模拟了气象站,有数据变化并告诉weatherdata有新数据了,然后waetherdata进行数据的更新();
       public void setData(float  temperature, float pressure,float humidity) {
            this.temperature = temperature;
            this.pressure = pressure;
            this.humidity = humidity;
            dataChange();
       }
}

公告板类:CurrentConditions

package com.java.Internetweather_1;

public class CurrentConditions {
   private float  temperature;
   private float pressure;
   private float humidity;
   
   public void updata( float  temperature, float pressure,float humidity) {
       this.temperature = temperature;
       this.pressure = pressure;
       this.humidity = humidity;
       //当有更新的时候,我们就直接显示
       display();
   }
   
   public void display() {
       System.out.println("****Taday temperature : "+temperature+"****");
       
       System.out.println("****Taday pressure: "+pressure+"****");
       
       System.out.println("****Taday humiduty: "+humidity+"****");
       
   }
}

测试类:InternetWeather

  package com.java.Internetweather_1;

public class InternetWeather {
   public static void main(String[] args) {
       InternetWeather internetWeather = new InternetWeather();
       
        
   }
   public InternetWeather() {
       CurrentConditions currentconditions = new CurrentConditions() ;
       WeatherData weatherData = new WeatherData(currentconditions) ;
       weatherData.setData(16, 160, 20);
   }

}

问题:当其他公司也需要气象站的消息,也想要做一个公告板的时候,我们需要在weatherdata类中的大它 change() 里加入其他公告板的初始化;每增加一个新的公司我们的weather data就要重新编译一遍,但是在正常的项目里面,weatherdata往往时是独立的进程,不会动不动就停下重新编译的,所以这个思路的拓展性很不好,所以接下来我们用观察者模式试试。

解决的问题:

1)其他第三方公司接入气象站获取数据的问题
2)在运行时动态添加第三方

方案二:观察者模式

了解观察者模式:
    就像定牛奶业务: 
    1)奶站:Subject
    2) 用户:Observer
    
Subject:登记注册,移除和通知
     Subject
     registerObserver()
     removeObserver()
     notifyObserver()
     
Observer:接收输入
       Observer
       update()
观察者模式:对象之间多对一依赖关系的一种设方案,被依赖的对象Subject ,依赖的对象是Observer,Subject通知Observer的变化

1)WeatherDataSubject

   //在原来的类中添加三个方法:登记注册,移除和通知,这里的观察者是公告板
    registerObserver()
    removeObserver()
    notifyObservers()
    
    getTemperature()
    getHumidity()
    getPressure()
    dataChange()  

2)CurrentConditionObservers

Updata()
display()         
//当公告板有增加或删除时,就会通过Updatable()告诉 WeatherDataSubject去登记注册,或移除
//当WeatherDataSubject 有数据变化的时候,就通过 notifyObservers()告诉CurrentConditionObservers去display();

代码实现:

1)Observer接口:

package com.java.internetweatherObservermode;

public interface Observer {
    public void update( float  temperature, float pressure,float humidity) ;
        
  }

2)Subject接口:

package com.java.internetweatherObservermode;

public interface Subject {
    public void registerObserver(Observer o);
    public void remodeObserver(Observer o);
    public void notifyObserver();
}

3)当前公告板类

package com.java.internetweatherMode;

import com.java.internetweatherObservermode.Observer;

//实现Observer接口(观察者)
public class CurrentConditions implements Observer{
    private float  temperature;
    private float pressure;
    private float humidity;
    @Override
    public void update(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        //当有更新的时候,我们就直接显示
        display();
    }
    public void display() {
        System.out.println("****Taday temperature : "+temperature+"****");
        
        System.out.println("****Taday pressure: "+pressure+"****");
        
        System.out.println("****Taday humiduty: "+humidity+"****");
        
    }

}

4)预测天气公告板类

package com.java.internetweatherMode;

import com.java.internetweatherObservermode.Observer;

//另外一个观察者

public class ForcastConditions implements Observer {
    private float  temperature;
    private float pressure;
    private float humidity;
    @Override
    public void update(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        //当有更新的时候,我们就直接显示
        display();
        
    }
    public void display() {
        System.out.println("****Tomorrow temperature : "+(temperature+Math.random())+"****");
        
        System.out.println("****Tomorrow pressure: "+(pressure+10*Math.random())+"****");
        
        System.out.println("****Tomorrow humiduty: "+(humidity+Math.random())+"****");
        
    }
}

5)天气数据类(数据的提供者,
实现Subject接口)

package com.java.internetweatherMode;

import java.util.ArrayList;


import com.java.internetweatherObservermode.Observer;
import com.java.internetweatherObservermode.Subject;
//实现Subject接口
public class WeatherDataSt implements Subject {
    private float temperature;
    private float humidity;
    private float pressure;
    //因为我们不知道以后观察者有点多少,所以我们使用ArrayList集合,完成相应的操作
    private ArrayList  observers;
    //有了公告板后,我们就可以把它当作一个属性,被接口使用
    private CurrentConditions currentConditions;
    //在构造函数里将观察者初始化
    public WeatherDataSt( ) {
         observers = new ArrayList();
        
    }
    @Override
    public void registerObserver(Observer o) {
        
          observers.add(o);
    }
    @Override
    public void remodeObserver(Observer o) {
        
         if(observers.contains(o))
         {
             observers.remove(o);
         }
    }
    @Override
    public void notifyObserver() {
                    for(int i = 0 ; i < observers.size(); i++ ) {
                observers.get(i).update(getTemperature(), getPressure(), getHumidity()); 
            }
    }

    public float getTemperature() {
        return temperature;
    }
    public float getHumidity() {
        return humidity;
    }
    public float getPressure() {
        return pressure;
    }
   public void dataChange() {
     //当有新的数据之后,我们就调用 notifyObserver() 
       notifyObserver() ;
   }
  //假设气象站有数据变化setData()模拟了气象站,有数据变化并告诉weatherdata有新数据了,然后waetherdata进行数据的更新();
   public void setData(float  temperature, float pressure,float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
   }

}

6)测试类:

package com.java.internetweatherMode;

public class InternerWeather {
        public static void main(String[] args) {
        
            WeatherDataSt weatherDataSt = new WeatherDataSt( ) ;
            CurrentConditions currentconditions = new CurrentConditions() ;
            ForcastConditions forcastconditions = new ForcastConditions();
            
            weatherDataSt.registerObserver(forcastconditions);
            weatherDataSt.registerObserver(currentconditions );
            
            weatherDataSt.setData(20, 150, 20);
            System.out.println("删除当前公告板的消息后");
        //此时就可以在这里直接添加或者删除观察者,而不需要在weatherdatast那操作了。           
           weatherDataSt.remodeObserver(currentconditions);
            weatherDataSt.setData(15, 180, 20);
            
            
        }
}

output:

****Tomorrow temperature : 20.050391790625735****
****Tomorrow pressure: 154.9485208171542****
****Tomorrow humiduty: 20.820273884785347****
****Taday temperature : 20.0****
****Taday pressure: 150.0****
****Taday humiduty: 20.0****
删除当前公告板的消息后
****Tomorrow temperature : 15.068996039881723****
****Tomorrow pressure: 189.28580553999814****
****Tomorrow humiduty: 20.16418761237121****

观察者模式的定义:

Observer模式是行为模式之一,它的作用是当一个对象的状态反思鞥变化时,能够子自动通知其他关联对象,自动刷新对象的状态。
Observer模式提供给关联对象一种同步通信的手段,使用某个对象与依赖它的其他对象之间保持状态同步。

个人在极客学院的视频学习笔记

你可能感兴趣的:(JAVA设计模式(2)- 观察者模式)