使用目的
降低交互对象的耦合度
定义
观察者模式:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
1对多的关系 ,1 是被观察者(主题),多是观察者。观察者通过订阅主题,以便在主题数据发生变化时,收到更新。
生活中的例子
以报纸或杂志的订阅分析
1.报社的业务出版报纸。
2.订阅某家报社的报纸后,只要报社出新报纸,就会给你送来,只要你是他的客户,就会源源不断收到新报纸。
3.当你不想看报纸的时候,只要取消订阅,那就不会再收到新的报纸。
4.只要报社还在运营,就会不断地有个人或单位订阅或取消订阅报纸。
通过图的方式描述观察者和被观察者的关系:
类图关系
实际应用
下面以气象站天气预报为例介绍观察者模式具体使用
我们要实现一个从气象站获取信息,实现目前状况(温度,湿度,气压)、气象统计、天气预报 三个功能的应用
类图关系应该是这样的:
首先是主题与观察者接口
public interface Subject {
/**
* 观察者与被观察者建立依赖关系
* @param o
*/
public void registerObserver(Observer o);
/**
* 取消观察者与被观察者的依赖关系
* @param o
*/
public void removeObserver(Observer o);
/**
* 数据更新通知观察者
*/
public void notifyObservers();
}
public interface Observer {
/**
* 所有的气象组件观察者实现此接口,这样当主题通知观察者时,有了一个共同的接口
* @param temp
* @param humidity
* @param pressure
*/
void update(float temp,float humidity,float pressure);
}
接下来是具体的 Subject 气象数据:
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers = new ArrayList();
}
/**
* 将观察者与自身建立依赖关系
*/
public void registerObserver(Observer o) {
// TODO Auto-generated method stub
observers.add(o);
}
/**
* 将观察者与自身解除依赖关系
*/
public void removeObserver(Observer o) {
// TODO Auto-generated method stub
int i = observers.indexOf(o);
if(i >= 0){
observers.remove(i);
}
}
public void notifyObservers() {
// TODO Auto-generated method stub
for(int i = 0;i < observers.size(); i++){
Observer observer = (Observer) observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged(){
notifyObservers();
}
/**
* 取到最新的温度 湿度 气压时,会发出测量数据改变,通知观察者
* @param temperature
* @param humidity
* @param pressure
*/
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//other method
}
举例以当前状况作为观察者的具体实现
/**
* 目前状况 温度 湿度 气压
* @author admin
*
*/
public class CurrentConditionsDisplay implements Observer,DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData){
this.weatherData = weatherData;
//注册依赖
weatherData.registerObserver(this);
}
public void display() {
// TODO Auto-generated method stub
System.out.println("Current conditions:"+temperature +"F degrees and "+
humidity+"% humidity");
}
/**
* 接收到 Subject 发来的数据更新
*/
public void update(float temp, float humidity, float pressure) {
// TODO Auto-generated method stub
this.temperature = temp;
this.humidity = humidity;
display();
}
}
/**
* 观察者模式
* @author admin
*
*/
public class WeatherStation {
public static void main(String[] args) {
// TODO Auto-generated method stub
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay conditionsDisplay =
new CurrentConditionsDisplay(weatherData);
// ForecastDisplay forecastDisplay =
// new ForecastDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
public interface DisplayElement {
void display();
}
这样,就实现了观察者模式使用。
Java 本身实现了观察者模式, 具体可以查看import java.util.Observable;和import java.util.Observer;
PS
欢迎爱学习的小伙伴加群一起进步:230274309 。
一起分享,一起进步!少划水,多晒干货!!欢迎大家!!!(进群潜水者勿加)