在现实世界中,许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。例如,某种商品的物价上涨时会导致部分商家高兴,而消费者伤心。气象局的天气预报与听众。股票价格与股民。
模式特点
定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。它是对象行为型模式。
观察者模式是一种对象行为型模式,其主要优点如下。
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
目标与观察者之间建立了一套触发机制。
它的主要缺点如下。
目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
//显示当前天气情况
public class CurrentConditions {
//温度 气压 湿度
private float temperature;
private float pressure;
private float humidity;
//更新天气情况,是由WeatherData 调用
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("*** Today Temperature:" + temperature + "***");
System.out.println("*** Today Pressure:" + pressure + "***");
System.out.println("*** Today Humidity:" + humidity + "***");
}
}
/**
* 核心类 包含最新的天气情况消息 含有currentConditions
* 当数据有更新时,主动调用 currentConditions的update方法(含有display),
* 这样他们就看到了最新的消息。
*/
public class WeatherData {
private float temperature;
private float pressure;
private float humidity;
private CurrentConditions currentConditions;
public WeatherData(CurrentConditions currentConditions) {
this.currentConditions = currentConditions;
}
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
public void dataChange() {
//调用接入方 的update
currentConditions.update(getTemperature(), getPressure(), getHumidity());
}
public void setData(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
//将最新的学习 推送给接入方 currentConditions
dataChange();
}
}
public static void main(String[] args) {
//接入方 CurrentConditions
CurrentConditions currentConditions = new CurrentConditions();
//创建 WeatherData 并将接入方 传递到 WeatherData中
WeatherData weatherData = new WeatherData(currentConditions);
weatherData.setData(30,150,40);
System.out.println("天气变化");
weatherData.setData(32,150,40);
}
jdk中观察者模式实现(Observable和Observer)
public static void main(String[] args) {
House house = new House(10000);
HousePriceObserver A = new HousePriceObserver("A");
HousePriceObserver B = new HousePriceObserver("B");
HousePriceObserver C = new HousePriceObserver("C");
house.addObserver(A);
house.addObserver(B);
house.addObserver(C);
System.out.println(house.toString());
house.setPrice(6000);
house.setPrice(8000);
}
当前房价为:10000.0
购物者C观察到房价已调整为: 6000.0
购物者B观察到房价已调整为: 6000.0
购物者A观察到房价已调整为: 6000.0
购物者C观察到房价已调整为: 8000.0
购物者B观察到房价已调整为: 8000.0
购物者A观察到房价已调整为: 8000.0
//房价
class House extends Observable {
private double price;
public House(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
if (this.price != price) {
this.price = price;
setChanged(); //标注价格已经被更改
this.notifyObservers(price); //通知观察者数据已被更改
}
}
@Override
public String toString() {
return "当前房价为:" + price;
}
}
//购房者
class HousePriceObserver implements Observer {
private String name;
public HousePriceObserver(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
//这里最好判断一下通知是否来自于房价,有可能来自其它地方
if (o instanceof House) {
System.out.println("购物者" + name + "观察到房价已调整为: " + arg);
}
}
}