文章目录

一、背景

二、JDK API

  • 通过继承java.util.Observable类就可以实现被观察者对象;
  • 通过实现java.util.Observer接口就可以实现观察者对象。
* @author  Chris Warth
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
* @see java.util.Observer
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
* @since JDK1.0
*/
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;

/** Construct an Observable with zero Observers. */

public Observable() {
obs = new Vector<>();
}
....
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}

public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Object[] arrLocal;

synchronized (this) {
/* We don't want the Observer doing callbacks into
* arbitrary code while holding its own Monitor.
* The code where we extract each Observable from
* the Vector and store the state of the Observer
* needs synchronization, but notifying observers
* does not (should not). The worst result of any
* potential race-condition here is that:
* 1) a newly-added Observer will miss a
* notification in progress
* 2) a recently unregistered Observer will be
* wrongly notified when it doesn't care
*/
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}

for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
....
}
* @author  Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
void update(Observable o, Object arg);
}

三、代码实战

  • 将股票这个被观察者对象继承Observable类:
  1. 定义股价、成交量、涨幅变量
  2. 添加构造函数
  3. 编写状态变化方法
  4. 重写toString方法
/**
* 通过JDK实现被观察者
*/
public class Stock extends Observable {

// 当前股价
private float price;

// 成交量
private float number;

// 涨幅
private float increase;

// 初始值
public Stock(float price, float number, float increase) {
this.price = price;
this.number = number;
this.increase = increase;
}

// 股票状态变化
public void stateChange(float price,float number,float increase) {
this.price = price;
this.number = number;
this.increase = increase;

// 状态发生变化
setChanged();

// 通知投资者
notifyObservers();
}

public float getPrice() {
return price;
}

public float getNumber() {
return number;
}

public float getIncrease() {
return increase;
}

@Override
public String toString() {
return "Stock{" +
"price=" + price +"元"+
", number=" + number +"手"+
", increase=" + increase +"%"+
'}';
}
}
  • 编写投资者观察者类,并实现Observer接口:
  1. 定义投资者名称变量
  2. 添加构造函数
  3. 重写update方法
/**
* 通过JDK实现观察者
*/
public class Investor implements Observer {

Observable observable;

// 投资者名称
private String name;



public Investor(String name, Observable observable) {
this.name = name;
this.observable = observable;
observable.addObserver(this);
}

@Override
public void update(Observable o, Object arg) {
if (o instanceof Stock) {
Stock stock = (Stock) o;

System.out.println(
name +"正在观察:{" +
"price=" + stock.getPrice() +"元"+
", number=" + stock.getNumber() +"手"+
", increase=" + stock.getIncrease() +"%"+
'}'
);
}

}

}
  • 编写测试类:
  1. 创建股票对象并初始化
  2. 创建三个投资者对象,并观察该股票
  3. 股票状态发生变化:跟踪投资者输出信息。
/**
* 通过JDK实现观察者模式测试程序
*/
public class Test {
public static void main(String[] args) {

Stock stock = new Stock(10,0,0);
System.out.println("股市开盘:"+stock.toString());

Investor investor1 = new Investor("张三",stock);

Investor investor2 = new Investor("李四",stock);

Investor investor3= new Investor("王五",stock);

System.out.println("股价发生变化---");
stock.stateChange((float) 10.5,100000,5);

System.out.println("张三退出观察:");
stock.deleteObserver(investor1);

System.out.println("股价又发生变化---");
stock.stateChange((float) 11,200000,10);

}
}

设计模式二补充:使用JDK内置API实现观察者模式_观察者模式

四、总结

  • 将股票类继承于Observable类,将投资者类实现Observer接口,可以方便的使用JDK内置API实现观察者模式。
  • 通过Observable类的addObserver,deleteObserver方法可以增中或删除观察者对象。
  • 被观察者先调用setChanged方法,将标记设为已更改状态,并通过notifyObservers方法通知观察者
  • 以上案例通过实现观察者类中的update(Observable o, Object arg)方法,拉取到了票据实时数据。