观察者模式在Java语言中的地位非常重要。在JDK的java.util包中,提供了Observable类以及Observer接口,它们构成了JDK对观察者模式的支持。如图22-5所示:
图22-5 JDK提供的Observable类及Observer接口结构图
(1) Observer接口
在java.util.Observer接口中只声明一个方法,它充当抽象观察者,其方法声明代码如下所示:
void update(Observable o, Object arg); |
当观察目标的状态发生变化时,该方法将会被调用,在Observer的子类中将实现update()方法,即具体观察者可以根据需要具有不同的更新行为。当调用观察目标类Observable的notifyObservers()方法时,将执行观察者类中的update()方法。
(2) Observable类
java.util.Observable类充当观察目标类,在Observable中定义了一个向量Vector来存储观察者对象,它所包含的方法及说明见表22-1:
表22-1 Observable类所包含方法及说明
方法名 | 方法描述 |
Observable() | 构造方法,实例化Vector向量。 |
addObserver(Observer o) | 用于注册新的观察者对象到向量中。 |
deleteObserver (Observer o) | 用于删除向量中的某一个观察者对象。 |
notifyObservers()和notifyObservers(Object arg) | 通知方法,用于在方法内部循环调用向量中每一个观察者的update()方法。 |
deleteObservers() | 用于清空向量,即删除向量中所有观察者对象。 |
setChanged() | 该方法被调用后会设置一个boolean类型的内部标记变量changed的值为true,表示观察目标对象的状态发生了变化。 |
clearChanged() | 用于将changed变量的值设为false,表示对象状态不再发生改变或者已经通知了所有的观察者对象,调用了它们的update()方法。 |
hasChanged() | 用于测试对象状态是否改变。 |
countObservers() | 用于返回向量中观察者的数量。 |
我们可以直接使用Observer接口和Observable类来作为观察者模式的抽象层,再自定义具体观察者类和具体观察目标类,通过使用JDK中的Observer接口和Observable类,可以更加方便地在Java语言中应用观察者模式。
java实现的小例子:
| 练习 Sunny软件公司欲开发一款实时在线股票软件,该软件需提供如下功能:当股票购买者所购买的某支股票价格变化幅度达到5%时,系统将自动发送通知(包括新价格)给购买该股票的所有股民。试使用观察者模式设计并实现该系统。 |
package com.zy;
import java.util.Observer;
import java.util.Observable;
//被观察者
class StockPrice extends Observable{
double price;
String stockName;
public StockPrice(String name,double price){
this.stockName=name;
this.price=price;
}
public void priceChanged(double price){
if((price-this.price)/price>0.05){
this.price=price;
System.out.println(this.stockName+"股票价格增长超过5%\n现在价格为:"+price);
setChanged();
notifyObservers(price);
}else{
System.out.println(this.stockName+"股票价格增长没超过5%\n现在价格为:"+price);
}
}
}
//观察者
class Investor implements Observer{
String name;
public Investor(String name){
this.name=name;
}
public void update(Observable o,Object arg){
System.out.println(this.name+"观察到 "+" 股票价格为:"+(Double)arg);
}
}
public class ObserverDemo {
public static void main(String args[]){
Investor v1=new Investor("zhangyao");
Investor v2=new Investor("zhangzhe");
Investor v3=new Investor("zhanghao");
StockPrice sp=new StockPrice("华能国际",19.2);
sp.addObserver(v1);
sp.addObserver(v2);
sp.addObserver(v3);
sp.priceChanged(39.34);
}
}