定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
可观察者继承Observable
(java.util.Observable)
观察者实现Observer
(java.util.Observer)接口
java.util
的实现换成另一套做法的实现setChanged()
方法被保护起来了。这意味着:除非你继承自Observable,否则你无法创建Observable实例并组合到你自己的对象中来。这个设计违反了第二个设计原则:多用组合,少用继承。public interface Subject {
/**
* 功能描述: 注册观察者
*
* @param o 观察者
* @return void
* @author liyf
*/
void registerObserver(Observer o);
/**
* 功能描述: 删除观察者
*
* @param o 观察者
* @return void
* @author liyf
*/
void removeObserver(Observer o);
/**
* 功能描述: 通知所有的观察者
*
* @param
* @return void
* @author liyf
*/
default void notifyObserver() {
notifyObserver(null);
}
/**
* 功能描述: 通知所有的观察者
*
* @param arg 推送的数据
* @return void
* @author liyf
*/
void notifyObserver(Object arg);
/**
* 功能描述: 标记被观察者对象已经改变
*
* @param
* @return void
* @author liyf
*/
void setChanged();
/**
* 功能描述:清除改变状态
*
* @param
* @return void
* @author liyf
*/
void clearChanged();
/**
* 功能描述: 查询被观察者对象是否改变
*
* @param
* @return boolean
* @author liyf
*/
boolean hasChanged();
}
被观察者应只有一个,所以使用了单例模式
public class WeatherStation implements Subject {
private WeatherData weatherData;
private boolean changed = false;
private List<Observer> list = new ArrayList<>();
private WeatherStation() {
}
private static class SingletonHolder {
private static final WeatherStation INSTANCE = new WeatherStation();
}
public static WeatherStation getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* 功能描述: 当气象站更新数据时,通知观察者
*
* @param
* @return void
* @author liyf
*/
public void measurementsChanged() {
setChanged();
notifyObserver(weatherData);
}
/**
* 功能描述: 更新数据
*
* @param weatherData 天气数据
* @return void
* @author liyf
*/
public void setMeasurements(WeatherData weatherData) {
this.weatherData = weatherData;
measurementsChanged();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
list.remove(o);
}
@Override
public void notifyObserver(Object arg) {
if (changed) {
for (Observer observer : list) {
observer.update(this, arg);
}
}
}
@Override
public void setChanged() {
changed = true;
}
@Override
public void clearChanged() {
changed = false;
}
@Override
public boolean hasChanged() {
return changed;
}
}
public interface Observer {
/**
* 功能描述:
*
* @param subject 被观察者
* @param arg 参数
* @return void
* @author liyf
*/
void update(Subject subject, Object arg);
}
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private WeatherData weatherData;
private Subject subject;
public CurrentConditionsDisplay(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void display() {
System.out.println("CurrentConditionsDisplay.weatherData = " + weatherData);
}
@Override
public void update(Subject subject, Object arg) {
if (subject instanceof WeatherStation) {
this.weatherData = (WeatherData) arg;
display();
}
}
}
public class StatisticsDisplay implements Observer, DisplayElement {
private WeatherData weatherData;
private Subject subject;
public StatisticsDisplay(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void display() {
System.out.println("StatisticsDisplay.weatherData = " + weatherData);
}
@Override
public void update(Subject subject, Object arg) {
if (subject instanceof WeatherStation) {
this.weatherData = (WeatherData) arg;
display();
}
}
}
public class TestWeatherStation {
@Test
public void test() {
WeatherStation weatherStation = WeatherStation.getInstance();
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherStation);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherStation);
WeatherData weatherData = new WeatherData(80, 65, 30.4f);
weatherStation.setMeasurements(weatherData);
weatherData.setHumidity(70);
weatherStation.setMeasurements(weatherData);
}
}
CurrentConditionsDisplay.weatherData = WeatherData(temperature=80.0, humidity=65.0, pressure=30.4)
StatisticsDisplay.weatherData = WeatherData(temperature=80.0, humidity=65.0, pressure=30.4)
CurrentConditionsDisplay.weatherData = WeatherData(temperature=80.0, humidity=70.0, pressure=30.4)
StatisticsDisplay.weatherData = WeatherData(temperature=80.0, humidity=70.0, pressure=30.4)