觀察者模式/ java實現附代碼 /

 /注:場景和例子引用github上的設計模式。傳送門:https://github.com/iluwatar/java-design-patterns/tree/master/observerjava

場景:

        一個天氣預報系統,凡是訂閱了改天氣預報的,當天氣發生改變的時候就把通知發送給全部訂閱該天氣預報的人。如獸人族(Orcs)和霍比特人(Hobitts)訂閱了該天氣預報系統,當天氣從晴變成雨天的時候,獸人族和霍比特人就收到了天氣變成雨天的通知。 若是還有其餘訂閱了該天氣預報的如人族(Terran),只須要在WeatherObserver中加入該人族(Terran)訂閱者,這樣當天氣發生改變的時候,人族也會收到天氣通知。git

意圖:

      定義對象間的一對多關係,當一個對象發生狀態更改時,會自動通知並更新全部依賴者。github

     

 

 

具體實現:

         訂閱天氣預報系統的便是觀察者(如Orcs、Hobitts),把這些訂閱天氣預報的人抽象成接口(WeatherObserver),全部訂閱該天氣預報的人都得實現這個接口才行。另外在天氣類(Weather)中也得開放一個接口讓他們訂閱,如使用List<Subscriber> observers 和寫一個方法 addObserver(WeatherObserver obs)來讓他們訂閱,一旦天氣發生變化就通知全部訂閱該天氣的方法 notifyAllObserver()。設計模式

 

talk is cheap,show me the code............................................................................................................................................................................................................................................................(分割線)數據結構

 先定義天氣類型(WeatherType.java),定義爲枚舉類型(sunny,rainny,windy,clod)ide

public enum WeatherType {
     SUNNY,WINDY,CLOD,RAINY;
	 
	 @Override
	 public String toString(){
		 return this.name().toLowerCase();
	 }
}

再將訂閱者抽象成一個接口(WeatherObserver.java),全部訂閱天氣預報系統的必須實現這個接口。測試

public interface WeatherObserver { public void Upadate(WeatherType currentWeather); }

天氣類(Weather)負責定義數據結構來接收訂閱者和通知更新訂閱者天氣變化。使用List<WeatherObserver>來接收訂閱者,定義方法addObserver來接收新的訂閱者和notifyAllObsever方法來更新訂閱者天氣狀態。this

import java.util.ArrayList; import java.util.List; public class Weather { private WeatherType currentWeather; private List<WeatherObserver> observers; public Weather(){ observers=new ArrayList<>(); currentWeather=WeatherType.SUNNY; } public void addObservers(WeatherObserver observer){ observers.add(observer); } public void removeObservers(WeatherObserver observer){ observers.remove(observer); } public  void timePasses(){ WeatherType[] enumValues=WeatherType.values(); /* for(WeatherType type:enumValues){ System.out.println(type); }*/
         //改變天氣,讓天氣的enum類型日後推一個
         currentWeather=enumValues[(currentWeather.ordinal() + 1) % enumValues.length]; System.out.println("The weather change to  "+currentWeather); notifyAllObserver(); } public void notifyAllObserver(){ for(WeatherObserver obs: observers){ obs.Upadate(currentWeather); } } }

添加兩個訂閱天氣預報的「人」,一個獸族(Orcs.java)一個霍比特人(Hobitts.java)。 如上面所說,要訂閱該天氣預報必須實現WeatherOberver接口。spa

public class Orcs implements WeatherObserver{ @Override public void Upadate(WeatherType currentWeather) { switch(currentWeather){ case CLOD: System.out.println("The orcs are freezing cold"); break; case SUNNY: System.out.println("The sun hurts the orcs' eyes."); break; case RAINY: System.out.println("The orcs are dripping wet."); break; case WINDY: System.out.println("The orc smell almost vanishes in the wind."); default: break; } } public class Hobbits implements WeatherObserver{ @Override public void Upadate(WeatherType currentWeather) { switch(currentWeather){ case CLOD: System.out.println("The Hobbits are freezing cold"); break; case SUNNY: System.out.println("The sun hurts the Hobbits' eyes."); break; case RAINY: System.out.println("The Hobbits are dripping wet."); break; case WINDY: System.out.println("The Hobbits smell almost vanishes in the wind."); default: break; } } }

寫一個主類來測試一下改功能(App.java)設計

public class APP { public static void main(String[] args){ Weather weather=new Weather(); weather.addObservers(new Orcs()); weather.addObservers(new Hobbits()); //weather.addObservers(new Terran()); weather.timePasses(); //weather.timePasses();
 } }

輸出:(即天氣從Sunny變成Windy的時候,訂閱該天氣的Orcs和Hobitts都收到了天氣改變的通知)

The weather change to  windy
The orc smell almost vanishes in the wind.
The Hobbits smell almost vanishes in the wind.

在如下任何狀況下使用觀察者模式:

  • 抽象有兩個方面,一個依賴於另外一個。將這些方面封裝在單獨的對象中能夠讓您獨立地更改和重用它們
  • 當更改一個對象須要更改其餘對象時,您不知道須要更改多少個對象
  • 當一個對象應該可以通知其餘對象,而不須要假設這些對象是誰。換句話說,你不但願這些對象緊密結合
相關文章
相關標籤/搜索