观察者模式中的观察者和被观察者类似于“订阅者”和“报社”的关系。订阅者作为报社的观察者来观察报社的状态,一旦报社的状态发生变更(出了新报纸),订阅者就可以做出相应的相应(订阅者去报社取阅报纸),同时,一个订阅者也可以在任何时候去订阅或者取消订阅一个报社的报纸(类似于观察者可以随时监听和取消监听一个被监听对象的状态),同时一个订阅者也可以同时订阅多家报社的报纸(类似于一个观察者可以同时观察多个对象的状态改变)。
在JDK中,已经为我们整合了观察者模式。运用起来也十分简单。只需要几部即可。
第一步:被观察的对象要继承Observerable类,这个类中已近提供了很多的实现,比如加入、删除一个监听此对象的监听器,当这个对象改变的时候,通知在这个被监听对象上注册的所有监听器。尤其注意:当被监听的对象状态改变后,一定要调用由Observeraboe继承而来的setChanged方法,因为在通知监听器之前,会判断此被监听的对象的状态是否改变,而判断的依据就是一个boolean值,必须通过setChanged()方法来标识此boolean变量。
public class WeatherData extends Observable {
private int temperature;
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
setChanged();//标识此被监听的对象的状态已经改变
notifyObservers();//通知所以监听这个对象的监听器。
}
}
第二部:观察者要实现Observer接口。并实现里面的update方法即可。
public class Board_2 implements Observer {
Observable observable;
public Board_2(Observable observable){
this.observable = observable;
this.observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if(observable instanceof WeatherData){
System.out.println("=====o2====="+((WeatherData)o).getTemperature());
System.out.println("=====w2====="+((WeatherData)observable).getTemperature());
}
}
}
测试代码如下:
public class ObserverTest {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
Board_1 b1 = new Board_1(weatherData);
Board_2 b2 = new Board_2(weatherData);
weatherData.setTemperature(100);
weatherData.setTemperature(200);
weatherData.setTemperature(300);
}
}
现有如下好处:满足如下三个设计原则
第一:封装变化:这个模式中,会改变的是被监听者的状态和他的监听者数量和类型,用这个模式,当这两个会改变的量发生改变的时候,我们都不用去改变被监听者对象。
第二:针对接口编程:被观察者利用的是观察者接口来通知观察者(JDK源码),而观察者利用的是被观察者接口向被观察者注册。
第三:多用组合,少用继承:利用组合将很多的观察者组合进被观察者中,而且实在运行时利用组合的方式产生的。