背景
在现实生活中,经常出现观察者模式这种场景,比如对于烧水这件事,水是我要观察的对象,那么我就是一个观察者,观察者模式一般是一种一对多的关系,可以有任意个(一个或多个)观察者对象同时监听某一个对象。监听的对象叫观察者(后面提到监听者,其实就指观察者,两者是等价的),被监听的对象叫被观察者(Observable,也叫主题Subject)。被观察者对象在状态上发生变化时,会通知所有观察者对象,使它们能够做出相应的变化(如自动更新自己的信息)。
实现
简单地说,当被观察对象发生某种变化时,被观察对象需要通知观察者,观察者接收到这种变化的信号后,然后做出一系列后续处理。接着这个老哥烧水的例子,他是手动实现观察者模式,思路非常清晰易懂。我将它改造成用java内置的API实现。
Java提供了Observable类和Observer接口,观察者需要实现Observer的方法update(),对被观察者发出的信号做出相应的响应。
下面是对正在烧的水进行观察:
public class WaterObservable extends Observable {
private double temperature;
private String status;
//封装水温和状态,传给观察者
private Info info;
/**GetterAndSetter
......
*/
public WaterObservable(){
this.temperature=0.0;
this.status="冷水";
info=new Info(temperature,status);
}
public WaterObservable(Observer observer){
this();
//注册观察者
addObserver(observer);
}
//烧水
public void boiledWater(double temperature){
setTemperature(temperature);
info.setTemperature(temperature);
if (temperature < 40) {
setStatus("冷水");
info.setStatus("冷水");
} else if (temperature >= 40 && temperature < 60) {
setStatus("温水");
info.setStatus("温水");
}else if (temperature >= 60 && temperature < 100 ) {
setStatus("热水");
info.setStatus("热水");
} else {
setStatus("开水");
info.setStatus("开水");
}
//状态改变
setChanged();
//通知观察者
notifyObservers(info);
}
class Info{
private double temperature;
private String status;
public Info(double temperature,String status){
this.status=status;
this.temperature=temperature;
}
/**GetterAndSetter
......
*/
}
}
下面是观察者:
public class WaterObserver implements Observer {
private String operation;
public WaterObserver(String operation){
this.operation=operation;
}
//被观察者发生变化后调用改方法
//这里的arg就是传递过来的info对象
@Override
public void update(Observable o, Object arg) {
System.out.println("TemperatureObserver observing...");
WaterObservable water=(WaterObservable)o;
WaterObservable.Info info=(WaterObservable.Info)arg;
System.out.println ("状态: "+info.getStatus()+" 水温:"+info.getTemperature());
if(info.getTemperature()==100){
System.out.println("操作: "+operation);
}
}
}
测试:
public class OBTest {
public static void main(String[] args) throws InterruptedException {
WaterObserver waterObserver = new WaterObserver("关火!!!");
WaterObservable waterObservable = new WaterObservable(waterObserver);
for(int i=1;i<=100;i++){
Thread.sleep(100);
waterObservable.boiledWater(i);
}
}
}