觀察者模式

觀察者模式:
定義了對象之間的一對多依賴,這樣一來,當一個對象改變狀態時,它的全部依賴者都會收到通知並自動更新。
設計原則:
爲了交互對象之間的鬆耦合設計而努力。
主題和觀察者定義了一對多的關係,參見報紙訂閱服務,報社是主題,用戶是觀察者們。
出版方+訂閱者=觀察者模式:
一、當報社出版新的報紙時,會推送給用戶。只要是報社的訂戶,就會一直收到新報紙。
二、取消報紙訂閱服務,就不會收到新報紙。
三、只要報社還在運營,就會一直有人向報社訂閱報紙或取消訂閱。
主題向觀察者推送消息,有兩種推送消息的方式,「推」和「拉」。
實例:創建一個氣象觀測站,WeatherData對象知道如何從氣象站獲取最新數據,隨即顯示在佈告板上。
如下是「推」的方式:主題推送數據給觀察者。
Java由內置的觀察者模式API,但如下用自定義的觀察者模式來實現「推」方式:
package mypackage;
public interface Subject {   //主題接口
  public void registerObserver(Observer o);//註冊觀察者
  public void removeObserver(Observer o);//移除觀察者
  public void notifyObservers();  //通知更新
}
package mypackage;
public interface Observer {   //觀察者接口
  public void update(float temp,float humidity,float pressure);
}
package mypackage;
public interface DisplayElement {  //佈告板接口
  public void display();
}
package mypackage;
import java.util.ArrayList;
public class WeatherData implements Subject { //具體的主題 WeatherData
 private ArrayList observers;
 private float temperature;
 private float humidity;
 private float pressure;
 public WeatherData() {
  observers=new ArrayList();
 }
 @Override
 public void registerObserver(Observer o) {
  observers.add(o);
 }
 @Override
 public void removeObserver(Observer o) {
  int i = observers.indexOf(o);
  if(i>0) {
   observers.remove(i);
  }
 }
 @Override
 public void notifyObservers() {
  for(int i = 0;i<observers.size();i++) {
   Observer observer=(Observer)observers.get(i);
   observer.update(temperature, humidity, pressure);
  }
 }
 public void measurementsChanged() {
  notifyObservers();
 }
 public void setMeasurements(float temperature,float humidity,float pressure) {//獲取氣象數據,這些數據由咱們手動賦值
  this.temperature=temperature;
  this.humidity=humidity;
  this.pressure=pressure;
  measurementsChanged();
 }
}
package mypackage;
public class CurrentConditionDisplay implements Observer, DisplayElement {//具體的觀察者,一個對象就是一個觀察者
 private float temperature;
 private float humidity;
 private Subject weatherData;
 
 
 
 public CurrentConditionDisplay(Subject weatherData) {
  this.weatherData=weatherData;
  weatherData.registerObserver(this);
 }
 @Override
 public void display() {
  System.out.println("Current conditions:"+temperature+"F degrees and"+humidity+"%humidity");
 }
 @Override
 public void update(float temperature, float humidity, float pressure) {//獲取更新數據
  this.temperature=temperature;
  this.humidity=humidity;
  display();
 }
 
}
package mypackage;
public class WeatherStation {
 public static void main(String[] args) {
  WeatherData weatherData = new WeatherData();
  
  CurrentConditionDisplay currentDisplay=new CurrentConditionDisplay(weatherData);//建立一個觀察者實例
  weatherData.setMeasurements(80, 65, 30.4f);//賦值氣象數據
  weatherData.setMeasurements(82, 70, 29.2f);
  weatherData.setMeasurements(78, 90, 29.2f);
 }
}
如下是「拉」的方式:
利用Java內置API實現:
package mypackage;
public interface DisplayElement { //自定義的佈告板接口
  public void display();
}
package mypackage;
import java.util.Observable;//Java內置的主題類
public class WeatherData extends Observable{
 private float temperature;
 private float humidity;
 private float pressure;
 
 public WeatherData() {}
 
 public void measurementsChangerd() {
  setChanged(); //須要,把changed標誌設置爲true,notifyObservers()纔會通知觀察者
  notifyObservers();
 }
 
 public void setMeasurements(float temperature,float humidity,float pressure) {
  this.temperature=temperature;
  this.humidity=humidity;
  this.pressure=pressure;
  measurementsChangerd();
 }
 public float getTemperature() {
  return temperature;
 }
 public float getHumidity() {
  return humidity;
 }
 public float getPressure() {
  return pressure;
 }
 
 
}

package mypackage;
import java.util.Observable;
import java.util.Observer; //Java內置的觀察者接口
public class CurrentConditionsDisplay implements Observer, DisplayElement{
 Observable observable;
 private float temperature;
 private float humidity;
 
 public CurrentConditionsDisplay(Observable observable) {
  this.observable=observable;
  observable.addObserver(this);
 }
 
 @Override
 public void display() {
  System.out.println("Current conditions:"+temperature+"F degrees and"+humidity+"%humidity");
  
 }
 
 @Override
 public void update(Observable o, Object arg) {
  if(o instanceof WeatherData) {  
   WeatherData weatherData = (WeatherData)o;
   this.temperature=weatherData.getTemperature(); //「拉」數據
   this.humidity=weatherData.getHumidity();
   display();
  }
  
 }
}
package mypackage;
public class WeatherStation {
 public static void main(String[] args) {
  WeatherData weatherData = new WeatherData();
  
  CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);
  weatherData.setMeasurements(80, 65, 30.4f);
  weatherData.setMeasurements(82, 70, 29.2f);
  weatherData.setMeasurements(78, 90, 29.2f);
 }
}
Java內置的Observable是一個類,類是單繼承的,限制了複用潛力。沒有Observable接口也沒法創建本身的實現 和Java內置的ObserverAPI搭配使用也沒法換成另外一套實現,好比setChanged()是受保護的,除非繼承, 不然沒法建立Observable實例並組合到本身的對象中。
相關文章
相關標籤/搜索