觀察者模式:對象之間多對一依賴的一種設計方案,被依賴的對象爲Subject,依賴的對象爲Observer,Subject通知Observer變化java
生活中的例子就是:訂報紙、頂牛奶dom
案例一:氣象站 一個普通的方案: ide
氣象站類測試
package com.java.test.internetweather; import java.util.Observable; public class WeatherData extends Observable { //氣象站的信息 //溫度氣壓溼度 private float mTemperatrue; private float mPressure; private float mHumidity; //外部接入的類 //公告板類 //須要得到氣象站的這些信息,而且氣象站的信息變化,也要跟着變 private CurrentConditions mCurrentConditions; //有參構造,須要傳入公告板類 public WeatherData(CurrentConditions mCurrentConditions) { this. mCurrentConditions= mCurrentConditions; } //三個get方法 public float getTemperature() { return mTemperatrue; } public float getPressure() { return mPressure; } public float getHumidity() { return mHumidity; //處理數據變化,數據變化,也要把變化的數據傳入公告板類,實現跟着變 } public void dataChange() { mCurrentConditions.update(this.getTemperature(),this.getPressure(),this.getHumidity()); } //設定數據 public void setData(float mTemperature,float mPressure,float mHumidity) { this.mTemperatrue=mTemperature; this.mPressure=mPressure; this.mHumidity=mHumidity; dataChange(); } } //公告板類 ```java package com.java.test.internetweather; public class CurrentConditions { //定義溫度氣壓溼度 private float mTemperature; private float mPressure; private float mHumidity; //設定三個參數 public void update(float mTemperature,float mPressure,float mHumidity) { this.mTemperature=mTemperature; this.mPressure=mPressure; this.mHumidity=mHumidity; display(); } //展現數據,在控制檯模擬 public void display() { System.out.println("***Today mTemperature: "+mTemperature+"***"); System.out.println("***Today mPressure: "+mPressure+"***"); System.out.println("***Today mHumidity: "+mHumidity+"***"); } } //測試類 ```java package com.java.test.internetweather; public class InternetWeather { public static void main(String[] args) { CurrentConditions mCurrentConditions; WeatherData mWeatherData; mCurrentConditions=new CurrentConditions(); mWeatherData=new WeatherData(mCurrentConditions); mWeatherData.setData(30, 150, 40); } }
這種方式耦合性仍是過高this
觀察者模式設計方案 設計
Subject接口類code
package com.java.test.internetweather.observer; public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
Observerserver
package com.java.test.internetweather.observer; public interface Observer { public void update(float mTemperatrue,float mPressure,float mHumidity); }
公告牌一 CurrentConditions對象
package com.java.test.internetweather.mode; import com.java.test.internetweather.observer.Observer; public class CurrentConditions implements Observer { /*私有變量*/ private float mTemperatrue; private float mPressure; private float mHumidity; @Override public void update(float mTemperatrue, float mPressure, float mHumidity) { // TODO Auto-generated method stub this.mHumidity = mHumidity; this.mPressure = mPressure; this.mTemperatrue = mTemperatrue; display(); } public void display() { System.out.println("***Today mTemperatrue:" + mTemperatrue + "***"); System.out.println("***Today mPressure:" + mPressure + "***"); System.out.println("***Today mHumidity:" + mHumidity + "***"); } }
公告牌二 ForcastConditionsblog
package com.java.test.internetweather.mode; import com.java.test.internetweather.observer.Observer; public class ForcastConditions implements Observer{ private float mTemperatrue; private float mPressure; private float mHumidity; @Override public void update(float mTemperatrue, float mPressure, float mHumidity) { // TODO Auto-generated method stub this.mTemperatrue=mTemperatrue; this.mPressure=mPressure; this.mHumidity=mHumidity; display(); } public void display() { System.out.println("**明天溫度:"+(mTemperatrue+Math.random())+"**"); System.out.println("**明天氣壓:"+(mPressure+10*Math.random())+"**"); System.out.println("**明天溼度:"+(mHumidity+Math.random())+"**"); } }
測試類 InternetWeather
package com.java.test.internetweather.mode; public class InternetWeather { public static void main(String[] args) { CurrentConditions mCurrentConditions; ForcastConditions mForcastConditions; WeatherDataSt mWeatherDataSt; mWeatherDataSt=new WeatherDataSt(); mCurrentConditions=new CurrentConditions(); mForcastConditions=new ForcastConditions(); mWeatherDataSt.registerObserver(mCurrentConditions); mWeatherDataSt.registerObserver(mForcastConditions); mWeatherDataSt.setData(30, 150, 40); mWeatherDataSt.removeObserver(mCurrentConditions); mWeatherDataSt.setData(40, 250, 50); } }
觀察者模式實現了比較好的低耦合特性,Object和Observer之間的關係只有實現了update方法這一關係,耦合性很是低
Java內置了觀察者對象 Observable Observer
Subject
WeatherData
package com.java.test.internetweather.jv; import java.util.Observable; public class WeatherData extends Observable{ private float mTemperatrue; private float mPressure; private float mHumidity; public float getTemperature() { return mTemperatrue; } public float getPressure() { return mPressure; } public float getHumidity() { return mHumidity; } public void dataChange() { //表示數據變化了 //從源碼中能夠看到裏面有個bool值變爲了true,下面那個方法會判斷這個是否爲true this.setChanged(); //這個方式是等觀察者本身拉取 //this.notifyObservers(); //這個方式是把信息主動推送給觀察者 this.notifyObservers(new Data(getTemperature(),getPressure(),getHumidity())); } public void setData(float mTemperatrue,float mPressure,float mHumidity) { this.mTemperatrue=mTemperatrue; this.mPressure=mPressure; this.mHumidity=mHumidity; dataChange(); } public class Data { public float mTemperatrue; public float mPressure; public float mHumidity; public Data(float mTemperatrue,float mPressure,float mHumidity) { this.mTemperatrue=mTemperatrue; this.mPressure=mPressure; this.mHumidity=mHumidity; } } }
公告板一
package com.java.test.internetweather.jv; import java.util.Observable; import java.util.Observer; import com.java.test.internetweather.jv.WeatherData.Data; public class CurrentConditions implements Observer { private float mTemperatrue; private float mPressure; private float mHumidity; @Override public void update(Observable arg0, Object arg1) { // TODO Auto-generated method stub this.mTemperatrue=((Data)(arg1)).mTemperatrue; this.mPressure=((Data)(arg1)).mPressure; this.mHumidity=((Data)(arg1)).mHumidity; display(); } public void display() { System.out.println("***Today mTemperatrue:" +mTemperatrue+"***"); System.out.println("***Today mPressure:" +mPressure+"***"); System.out.println("***Today mHumidity:" +mHumidity+"***"); } }
公告板二 ForcastConditions
package com.java.test.internetweather.mode; import com.java.test.internetweather.observer.Observer; public class ForcastConditions implements Observer{ private float mTemperatrue; private float mPressure; private float mHumidity; @Override public void update(float mTemperatrue, float mPressure, float mHumidity) { // TODO Auto-generated method stub this.mTemperatrue=mTemperatrue; this.mPressure=mPressure; this.mHumidity=mHumidity; display(); } public void display() { System.out.println("**明天溫度:"+(mTemperatrue+Math.random())+"**"); System.out.println("**明天氣壓:"+(mPressure+10*Math.random())+"**"); System.out.println("**明天溼度:"+(mHumidity+Math.random())+"**"); } }
測試類
package com.java.test.internetweather.jv; public class InternetWeather { public static void main(String[] args) { CurrentConditions mCurrentConditions; ForcastConditions mForcastConditions; WeatherData mWeatherData; mCurrentConditions=new CurrentConditions(); mForcastConditions=new ForcastConditions(); mWeatherData=new WeatherData(); mWeatherData.addObserver(mCurrentConditions); mWeatherData.addObserver(mForcastConditions); mWeatherData.setData(30, 150, 40); mWeatherData.deleteObserver(mCurrentConditions); mWeatherData.setData(35, 150, 60); } }