观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
使用场景
对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。一般用于需要推送消息当场景,如天气推送,公众号关注后信息推送等。
观察者模式具体实现
1. 主题接口
对象通过此接口注册为观察者或者把自己从观察者删除。
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();// 当主题状态改变时,这个方法会被调用,以通知所有当观察者。
}
2.观察者接口
所有潜在的观察者必须实现观察者接口,当主题状态改变时他被调用。
public interface Observer {
void update(float temp,float humidity,float pressure);
}
3.具体主题
一个具体主题实现主题接口。
public class WeatherData implements Subject {
private ArrayList<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
// TODO Auto-generated constructor stub
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
// TODO Auto-generated method stub
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
// TODO Auto-generated method stub
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
@Override
public void notifyObservers() {
// TODO Auto-generated method stub
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
4.具体观察者
具体观察者必须注册具体主题,以便接收更新。
public class TemperatureDisplay implements Observer, DisplayElement {
private float temperature;
public TemperatureDisplay(Subject weatherData) {
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("temperature:" + temperature);
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
display();
}
}
其他两个具体观察者代码就不展示了。
5.测试类
public class WeatherStation {
public static void main(String[] arges) {
WeatherData weatherData = new WeatherData();
new TemperatureDisplay(weatherData);
new HumidityDisplay(weatherData);
new PressureDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(70, 61, 20.4f);
}
}
运行结果
temperature:80.0
humidity:65.0
pressure:30.4
temperature:70.0
humidity:61.0
pressure:20.4
优点
- 观察者模式提供了一套对象设计,让主题和观察者之间松耦合。
缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
当然,Java内部本身也有观察者模式,只是可拓展性可能没有自己设计的好。
网友评论