觀察者模式是一種常見的設(shè)計模式,顧名思義有觀察者與被觀察者剔宪,被觀察者的狀態(tài)有變動會通知觀察者拂铡,觀察者會收到通知壹无,進(jìn)而做進(jìn)一步的操作
要實現(xiàn)觀察者模式我們要首先思考下面幾個問題:
1. 觀察者的實現(xiàn)
2. 被觀察者的實現(xiàn)
3. 被觀察者狀態(tài)變更是怎么通知觀察者
4. 觀察者收到通知如何處理接下來的行為
### 觀察者的實現(xiàn)
`
public interface Observer {
? ? void update(Observable o, Object arg);
}
`
java提供了一個Observer接口,并有一個 update 方法感帅。觀察者只需要實現(xiàn)Observer接口斗锭,并實現(xiàn)update方法,表示收到被觀察者變更通知之后的行為
`
public class CurrentCondition implements Observer {
? ? private float temperature;
? ? private float pressure;
? ? private float humitidy;
? ? public void display(){
? ? ? ? System.out.println(temperature+","+pressure+","+humitidy);
? ? }
? ? @Override
? ? public void update(Observable o, Object arg) {
? ? ? ? this.temperature = ((WetherData)o).getTemperature();
? ? ? ? this.pressure = ((WetherData)o).getPressure();
? ? ? ? this.humitidy = ((WetherData)o).getHumidity();
? ? ? ? display();
? ? }
}
`
### 被觀察者
同樣java提供了Observable類失球,被觀察者需要繼承該類
`
public class Observable {
? ? private boolean changed = false;
? //用來保存觀察者岖是,遍歷發(fā)通知
? ? private Vector<Observer> obs;
? ? 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);
? ? }
? ? /*
? ? 當(dāng)本觀察者發(fā)生變化,需要先講change設(shè)置為true实苞,就會通知所有的注冊在 obs 變量里的觀察者豺撑,
? ? 會調(diào)用觀察者實現(xiàn)的update方法
? ? 再用clearChange方法將change設(shè)為false,表示不再變化
? ? */
? ? public void notifyObservers() {
? ? ? ? notifyObservers(null);
? ? }
? ? public void notifyObservers(Object arg) {
? ? ? ? Object[] arrLocal;
? ? ? ? synchronized (this) {
? ? ? ? ? ? if (!changed)
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? arrLocal = obs.toArray();
? ? ? ? ? ? clearChanged();
? ? ? ? }
? ? ? ? for (int i = arrLocal.length-1; i>=0; i--)
? ? ? ? ? ? ((Observer)arrLocal[i]).update(this, arg);
? ? }
? ? /**
? ? * Clears the observer list so that this object no longer has any observers.
? ? */
? ? public synchronized void deleteObservers() {
? ? ? ? obs.removeAllElements();
? ? }
? ? /**
? ? * Marks this <tt>Observable</tt> object as having been changed; the
? ? * <tt>hasChanged</tt> method will now return <tt>true</tt>.
? ? */
? ? protected synchronized void setChanged() {
? ? ? ? changed = true;
? ? }
? ? /**
? ? * Indicates that this object has no longer changed, or that it has
? ? * already notified all of its observers of its most recent change,
? ? * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.
? ? * This method is called automatically by the
? ? * <code>notifyObservers</code> methods.
? ? *
? ? * @see? ? java.util.Observable#notifyObservers()
? ? * @see? ? java.util.Observable#notifyObservers(java.lang.Object)
? ? */
? ? protected synchronized void clearChanged() {
? ? ? ? changed = false;
? ? }
? ? /**
? ? * Tests if this object has changed.
? ? *
? ? * @return? <code>true</code> if and only if the <code>setChanged</code>
? ? *? ? ? ? ? method has been called more recently than the
? ? *? ? ? ? ? <code>clearChanged</code> method on this object;
? ? *? ? ? ? ? <code>false</code> otherwise.
? ? * @see? ? java.util.Observable#clearChanged()
? ? * @see? ? java.util.Observable#setChanged()
? ? */
? ? public synchronized boolean hasChanged() {
? ? ? ? return changed;
? ? }
? ? /**
? ? * Returns the number of observers of this <tt>Observable</tt> object.
? ? *
? ? * @return? the number of observers of this object.
? ? */
? ? public synchronized int countObservers() {
? ? ? ? return obs.size();
? ? }
}
`
實現(xiàn)如下:
`
public class WetherData extends Observable {
? ? private float temperature;
? ? private float pressure;
? ? private float humidity;
? ? public float getTemperature() {
? ? ? ? return temperature;
? ? }
? ? public void setTemperature(float temperature) {
? ? ? ? this.temperature = temperature;
? ? }
? ? public float getPressure() {
? ? ? ? return pressure;
? ? }
? ? public void setPressure(float pressure) {
? ? ? ? this.pressure = pressure;
? ? }
? ? public float getHumidity() {
? ? ? ? return humidity;
? ? }
? ? public void setHumidity(float humidity) {
? ? ? ? this.humidity = humidity;
? ? }
? ? public void setData(float temperature,float pressure,float humidity){
? ? ? ? this.temperature = temperature;
? ? ? ? this.pressure = pressure;
? ? ? ? this.humidity = humidity;
? ? ? //需要先調(diào)用setChanged()方法黔牵,
? ? ? ? setChanged();
? ? ? ? notifyObservers();? //這個方法里面會將change的狀態(tài)清除
? ? }
}
`
`
public class Wether {
? ? public static void main(String[] args) {
? ? ? ? WetherData wetherData = new WetherData();
? ? ? ? CurrentCondition currentCondition = new CurrentCondition();
? ? ? ? wetherData.addObserver(currentCondition);
? ? ? ? wetherData.setData(112,22,221);
? ? }
}
`