觀察者設計模式:時當一個對象發生指定的動做時,要經過另外的對象作出相應的處理。設計模式
步驟:
1. A對象發生指定的動做是,要通知B,C,D...對象作出相應的處理,這時候應該把B,C,D...對象針對A對象的動做作出的相應處理方法定義在接口上(這是一種規範,凡事須要A對象通知的對象,都要實現該接口)。
2. 在A對象維護接口的引用,當A對象發生指定的動做這時候便可調用接口中的方法。dom
觀察者模式的應用場景:ide
1. 對一個對象狀態的更新,須要其餘對象同步更新,並且其餘對象的數量動態可變。this
2.對象僅須要將本身的更新通知給其餘對象而不須要知道其餘對象的細節。spa
假設有一個例子:設計
氣象臺天天都會更新天氣預報,訂閱的人羣均可以在每次氣象臺發佈天氣預報,均可以接收到天氣預報信息.訂閱人羣能夠根據天氣預報信息作出相應處理code
被觀察對象(Subject)server
1 /* 2 * 氣象臺類 3 * 4 */ 5 public class WeatherStation { 6 7 private String[] weatherArr = {"大雨","大雪","颱風","霧霾","多雲","晴"}; 8 private String weatherDesc = weatherArr[0]; 9 private ArrayList<IWeather> list = new ArrayList<IWeather>(); 10 11 //對外提供一個方法添加天氣預報更新時,要通知的對象 12 public void add(IWeather weather){ 13 this.list.add(weather); 14 } 15 16 //對外提供一個方法取消訂閱天氣預報 17 public void remove(IWeather weather){ 18 if(weatherArr.length>0){ 19 for (int i = 0; i < weatherArr.length; i++) { 20 if(list.get(i).equals(weather)){ 21 this.list.remove(i); 22 break; 23 } 24 } 25 26 } 27 } 28 29 30 //開始天氣預報 31 public void startWeatherForecast(){ 32 new Thread(){ 33 @Override 34 public void run() { 35 while(true){ 36 updateWeather();//每3秒鐘更新一次天氣預報 (模擬天天氣象臺自動更新天氣預報) 37 for (IWeather weather : list) { 38 weather.updateWeather(weatherDesc); 39 } 40 try { 41 Thread.sleep(3000); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 46 } 47 } 48 }.start(); 49 50 } 51 52 53 //氣象臺更新天氣 54 public void updateWeather(){ 55 Random random = new Random(); 56 int n = random.nextInt(weatherArr.length); 57 this.weatherDesc = weatherArr[n]; 58 System.out.println("氣象臺發佈天氣預報:"+this.weatherDesc); 59 } 60 61 }
全部訂閱的羣體必須具備一個共同updateWeather的方法(實現該接口),這樣氣象臺發佈新天氣預報時候,便可經過調用訂閱對象執行該方法,達到通知目的。對象
/* * 一個接口規範,實現了該接口對象所要作的動做。 * 實現該接口的對象當氣象臺天氣預報更新時執行 * {"大雨","大雪","颱風","霧霾","多雲","晴"} */ public interface IWeather { public void updateWeather(String weatherDesc); }
訂閱的羣體類 觀察者對象Observerblog
1 /* 2 * 可能訂閱羣個之一,工做者 3 * 4 */ 5 public class Emp implements IWeather { 6 7 String name; 8 int age; 9 10 public Emp(String name, int age) { 11 this.name = name; 12 this.age = age; 13 } 14 15 //{"大雨","大雪","颱風","霧霾","多雲","晴"} 16 @Override 17 public void updateWeather(String weatherDesc) { 18 System.out.println(this.name+":收到天氣預報 "+weatherDesc); 19 } 20 }
-
/* * 可能訂閱羣體之一, 學生 */ public class Student implements IWeather { String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } //{"大雨","大雪","颱風","霧霾","多雲","晴"} @Override public void updateWeather(String weatherDesc) { System.out.println(this.name+":收到天氣預報 "+weatherDesc); } }
Main、
1 public class WeatherMain { 2 3 public static void main(String[] args) { 4 WeatherStation weatherStation = new WeatherStation(); 5 6 Student s1 = new Student("小明", 10); 7 Student s2 = new Student("小美", 10); 8 Emp e1 = new Emp("大明", 10); 9 Emp e2 = new Emp("大美", 10); 10 weatherStation.add(s1); 11 weatherStation.add(s2); 12 weatherStation.add(e1); 13 weatherStation.add(e2); 14 weatherStation.remove(e2); 15 weatherStation.startWeatherForecast(); 16 } 17 18 }
由於「大美」取消了天氣預報,因此沒有收到天氣預報通知
執行結果:
氣象臺發佈天氣預報:大雪
小明:收到天氣預報 大雪
小美:收到天氣預報 大雪
大明:收到天氣預報 大雪
氣象臺發佈天氣預報:霧霾
小明:收到天氣預報 霧霾
小美:收到天氣預報 霧霾
大明:收到天氣預報 霧霾
氣象臺發佈天氣預報:颱風
小明:收到天氣預報 颱風
小美:收到天氣預報 颱風
大明:收到天氣預報 颱風
氣象臺發佈天氣預報:晴
小明:收到天氣預報 晴
小美:收到天氣預報 晴
大明:收到天氣預報 晴
氣象臺發佈天氣預報:霧霾
小明:收到天氣預報 霧霾
小美:收到天氣預報 霧霾
大明:收到天氣預報 霧霾
...