介绍
多个其他类想对某一个类的属性实现同步时使用
原理
对原理类图的说明-即(命名模式的角色及职责)
- Subject接口目的是管理观察者,registerObserver注册观察者,removeObserver移除观察者,notifyObservers通知观察者
- 数据源类就是观察者观察的目标,数据源需要提前把观察者注册到observers集合中,当数据源类数据更新时,能自身通知各个观察者或者提供接口让观察者调用查看最新数据。
- Observer是观察者的一个抽象接口,update方法是当数据源信息更新时,同步到观察者上的数据的方法
案例
天气预报项目需求,具体要求如下:
- 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。
- 需要设计开放型API,便于其他第三方也能接入气象站获取数据。
- 提供温度、气压和湿度的接口
- 测量数据更新时,要能实时的通知给第三方
//Subject三个方法都是操作的观察者集合的
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
//WeatherData(天文台)实现Subject实现操作观察者的方法
public class WeatherData implements Subject{
private double temperature;
private double pressure;
private double humidity;
private ArrayList<Observer> observers = new ArrayList<>();
public double getTemperrature() {
return temperature;
}
public double getPressure() {
return pressure;
}
public double getHumidity() {
return humidity;
}
public void dataChange(){
notifyObservers();
}
public void setWeatherData(double temperature,double pressure,double humidity){
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
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 observer : observers) {
observer.update(this.temperature,this.pressure,this.humidity);
}
}
}
//抽象观察者接口
public interface Observer {
public void update(double temperature,double pressure,double humidity);
}
//新浪观察者实现类
public class xinlang implements Observer{
private double temperature;
private double pressure;
private double humidity;
@Override
public void update(double temperrature, double pressure, double humidity) {
this.temperature = temperrature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
private void display() {
System.out.println("新浪-------温度为 "+ temperature + "度--------");
System.out.println("新浪-------气压为 "+ pressure + "帕--------");
System.out.println("新浪-------湿度为 "+ humidity + "%--------");
}
}
//百度观察者实现类
public class Baidu implements Observer{
private double temperature;
private double pressure;
private double humidity;
@Override
public void update(double temperrature, double pressure, double humidity) {
this.temperature = temperrature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
private void display() {
System.out.println("百度-------温度为 "+ temperature + "度--------");
System.out.println("百度-------气压为 "+ pressure + "帕--------");
System.out.println("百度-------湿度为 "+ humidity + "%--------");
}
}
//Client端测试
public class Client {
public static void main(String[] args) {
//创建WeatherData天气数据对象
WeatherData weatherData = new WeatherData();
//创建观察者
Observer observer1 = new Baidu();
Observer observer2 = new xinlang();
//注册观察者
weatherData.registerObserver(observer1);
weatherData.registerObserver(observer2);
//天文台数据改变
weatherData.setWeatherData(30,150,60);
}
}
观察者模式的好处
- 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。
- 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类WeatherData不会修改代码,遵守了ocp原则。
个人总结
此模式的核心是使用一个接口把全部观察者统一接管了,再在数据源类中用集合统一管理所有观察者,核心的方法是
1.注册观察者
2.移除观察者
3.通知所有观察者