觀察者模式允許多個觀察者訂閱一個主題,當主題的狀態發生變化時,能夠將這種變化通知到每個觀察者,從主題的角度看,這是典型的一對多關系,即一個主題可以對應多個觀察者,以訂閱郵件為例,當訂閱某一類主題內容(例如娛樂新聞,動漫等)時,如果該主題的內容有更新,那么每一個訂閱該主題的人都會受到一封內容更新的郵件,這便是典型的觀察者模式,
要實作郵件訂閱的功能,需要先定義一個主題介面,主題介面需要能夠隨時添加或者洗掉訂閱人(觀察者),并且在有內容更新時通知觀察者,其定義如下:
1 public interface Subject { 2 //添加觀察者 3 void registerObserver(Observer observer); 4 5 //移除觀察者 6 void removeObserver(Observer observer); 7 8 //有新內容時通知觀察者 9 void notifyObserver();10 }
與主題介面對應的是觀察者介面,介面很簡單,在有內容的時候更新狀態:
1 public interface Observer{2 void update(); //更新狀態3 }
主題介面有許多實作,這里選擇娛樂新聞主題作為例子:
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class EntertainmentSubject implements Subject{ 5 6 List<Observer> observerList; 7 8 public EntertainmentSubject(){ 9 this.observerList = new ArrayList<>();10 }11 12 @Override13 public void registerObserver(Observer observer) {14 this.observerList.add(observer);15 }16 17 @Override18 public void removeObserver(Observer observer) {19 int i = observerList.indexOf(observer);20 if(i >= 0){21 observerList.remove(i);22 }23 }24 25 @Override26 public void notifyObserver() {27 for(Observer observer : observerList){28 observer.update();29 }30 }31 32 // 假設內容變化時會呼叫這個介面33 public void contentUpdated(){34 notifyObserver();35 }36 }
主題需要在內容發生變化的時候通知所有的觀察者,這里使用contentUpdated()方法來實作,至于主題內容變化如何呼叫contentUpdated()方法則不在本文的討論范圍內,這里假設只要主題有更新就會呼叫這個方法,
接下來定義兩個具體的觀察者:
1 public class ConcreteObserver1 implements Observer{ 2 3 Subject subject; 4 public ConcreteObserver1(Subject subject) { 5 this.subject = subject; 6 } 7 8 @Override 9 public void update() {10 System.out.println("ConcreteObserver1, 給你發個郵件,因為這里有新內容了,,,");11 }12 }
1 public class ConcreteObserver2 implements Observer{ 2 3 Subject subject; 4 public ConcreteObserver2(Subject subject) { 5 this.subject = subject; 6 } 7 8 @Override 9 public void update() {10 System.out.println("ConcreteObserver2, 給你發個郵件,因為這里有新內容了,,,");11 }12 }
好了,所有的類都準備就緒,是時候寫個測驗來看一下觀察者模式的使用了:
1 public class ObserverTest { 2 public static void main(String[] args){ 3 EntertainmentSubject subject = new EntertainmentSubject(); 4 ConcreteObserver1 observer1 = new ConcreteObserver1(subject); 5 ConcreteObserver2 observer2 = new ConcreteObserver2(subject); 6 subject.registerObserver(observer1); 7 subject.registerObserver(observer2); 8 subject.contentUpdated(); //模擬內容更新 9 10 subject.removeObserver(observer1); //observer退訂11 subject.contentUpdated();12 }13 }
輸出:
ConcreteObserver1, 給你發個郵件,因為這里有新內容了,,,ConcreteObserver2, 給你發個郵件,因為這里有新內容了,,,ConcreteObserver2, 給你發個郵件,因為這里有新內容了,,,開始的時候有兩個觀察者,內容更新的時候兩個觀察者都收到了通知,后來observer1取消了訂閱,更新的時候就不再通知這個觀察者了,
當然,這里的觀察者模式的邏輯很簡單,現實中用到的觀察者模式比這要復雜許多,不過底層的結構大體相似,而且,Java也提供了觀察者模式的相關實作Observable和Observer,使用的時候需要將Subject換成Observable,需要注意的是Observable是類而不是介面,所以如果你的類已經繼承了其他類,就無法使用Java的這套API了,
參考:
<<Head First設計模式>>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/44339.html
標籤:設計模式
上一篇:設計模式-結構型-代理模式
下一篇:SSH框架之Spring第四篇
