观察者模式对象间建立一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。 观察者模式可在主题处push或者pull数据,push方式被认为更正确的方式。以下第一个实例中用push,第二个用pull。
java类图
java代码
public interface Subject {
void register(Observer observer);
void remove(Observer observer);
void notifyObserver();
}
public class WeatherData implements Subject {
private ArrayList<Observer> observers;
private int temperature;
private int humidity;
private int pressure;
public WeatherData() {
observers =
new ArrayList<>();
}
@Override
public void register(Observer observer) {
if (!observers.contains(observer)) {
observers.add(observer);
}
}
@Override
public void remove(Observer observer) {
int index = observers.indexOf(observer);
if (index >=
0) {
observers.remove(index);
}
}
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void setData(
int temperature,
int humidity,
int pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObserver();
}
}
public interface Display {
void display();
}
public interface Observer {
void update(
int temperature,
int humidity,
int pressure);
}
public class WeatherDisplay implements Observer, Display {
private Subject subject;
private int temperature;
private int humidity;
private int pressure;
public WeatherDisplay(Subject subject) {
this.subject = subject;
subject.register(
this);
}
@Override
public void display() {
System.out.println(
"temperature=" + temperature +
", humidity=" + humidity +
", pressure=" + pressure);
}
@Override
public void update(
int temperature,
int humidity,
int pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
}
public class ChangeDisplay implements Observer, Display {
private Subject subject;
private int temperature;
private int humidity;
private int preTemperature;
private int preHumidity;
public ChangeDisplay(Subject subject) {
this.subject = subject;
subject.register(
this);
}
@Override
public void display() {
System.out.println(
"temperatureChange=" + displayCal(temperature, preTemperature) +
", humidityChange=" + displayCal(humidity, preHumidity));
}
public String
displayCal(
int now,
int pre) {
int difference = now - pre;
if (difference >
0) {
return "↑";
}
else if (difference <
0) {
return "↓";
}
else {
return "-";
}
}
@Override
public void update(
int temperature,
int humidity,
int pressure) {
preTemperature =
this.temperature;
preHumidity =
this.humidity;
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
public class Test {
public static void main(String[] args) {
new Test().test();
}
private void test() {
WeatherData weatherData =
new WeatherData();
WeatherDisplay weatherDisplay =
new WeatherDisplay(weatherData);
ChangeDisplay changeDisplay =
new ChangeDisplay(weatherData);
weatherData.setData(
10,
23,
2);
weatherData.setData(
8,
24, -
1);
}
}
注:
主题直接将数据推送给观察者,属于push方式 观察者模式定义了对象间的一对多关系 主题用一个共同的接口来更新观察者 观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口 有多个观察者时,不可以依赖特定的通知顺序
java自带观察者接口
类图
java代码
public class WeatherData extends Observable {
private int temperature;
private int humidity;
private int pressure;
public void setData(
int temperature,
int humidity,
int pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
setChanged();
notifyObservers(
"push object");
}
public int getTemperature() {
return temperature;
}
public int getHumidity() {
return humidity;
}
public int getPressure() {
return pressure;
}
}
public interface Display {
void display();
}
public class WeatherDisplay implements Observer, Display {
private Observable observable;
private int temperature;
private int humidity;
private int pressure;
public WeatherDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(
this);
}
@Override
public void display() {
System.out.println(
"temperature=" + temperature +
", humidity=" + humidity +
", pressure=" + pressure);
}
@Override
public void update(Observable o, Object arg) {
if (o
instanceof WeatherData) {
WeatherData weatherData = (WeatherData) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
this.pressure = weatherData.getPressure();
System.out.println(
"Object arg is " + arg);
display();
}
}
}
public class ChangeDisplay implements Observer, Display {
private Observable observable;
private int temperature;
private int humidity;
private int preTemperature;
private int preHumidity;
public ChangeDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(
this);
}
@Override
public void display() {
System.out.println(
"temperatureChange=" + displayCal(temperature, preTemperature) +
", humidityChange=" + displayCal(humidity, preHumidity));
}
public String
displayCal(
int now,
int pre) {
int difference = now - pre;
if (difference >
0) {
return "↑";
}
else if (difference <
0) {
return "↓";
}
else {
return "-";
}
}
@Override
public void update(Observable o, Object arg) {
if (o
instanceof WeatherData) {
WeatherData weatherData = (WeatherData) o;
preTemperature =
this.temperature;
preHumidity =
this.humidity;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
System.out.println(
"Object arg is " + arg);
display();
}
}
}
public class Test {
public static void main(String[] args) {
new Test().test();
}
private void test() {
WeatherData weatherData =
new WeatherData();
WeatherDisplay weatherDisplay =
new WeatherDisplay(weatherData);
ChangeDisplay changeDisplay =
new ChangeDisplay(weatherData);
weatherData.setData(
10,
23,
2);
weatherData.setData(
8,
24, -
1);
}
}
注:
主题将自己的引用推送给观察者,观察者主动从主题中获取数据,属于pull方式 java.util.Observable是一个类,无法自定义实现,而且也无法再继承其他类。
参考文章 Head First 设计模式