閱讀《Design pattern》-觀察者模式
阿新 • • 發佈:2020-09-09
摘抄《設計模式》
意圖: 定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新 別名: 依賴(dependent),釋出-訂閱(publish-subscribe) 適用性: 在以下情況下可以使用觀察者模式: 一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這二者封裝在獨立的物件中,以使它們可以各自獨立地改變和複用。 對一個物件的改變需要同時改變其他物件,而不知道具體由多少物件需要改變。 一個物件必須通知其他物件,而他又不能假定其他物件是誰。換言之,你不希望這些物件緊密耦合的。簡單一句話:目標狀態變化,觸發所有觀察者變化。 注意:一對多的關係,一個目標,多個觀察者 目標提供一個方法:用於附上觀察者,便於notify(通知) 觀察者在初始時,關注(訂閱)目標,並附上在目標上。釋放時,取消關注(訂閱),移除。
1 /** 2 * 觀察者模式-目標介面 3 */ 4 public interface ISubject { 5 /** 6 * 附上觀察者 7 * @param observer 觀察者 8 */ 9 public void attach(IObserver observer); 10 11 /** 12 * 移除觀察者 13 * @param observer 觀察者 14 */ 15 public void detach(IObserver observer);16 17 /** 18 * 通知所有觀察者 19 */ 20 public void notifyAllObserver(); 21 }
1 /** 2 * 觀察者模式-觀察者介面 3 */ 4 public interface IObserver { 5 /** 6 * 訂閱目標 7 * @param subject 目標 8 */ 9 public void subscribe(ISubject subject); 10 11 /** 12 * 取消訂閱 13 */ 14public void unsubscribe(); 15 16 /** 17 * 業務更新 18 * @param subject 目標 19 */ 20 public void update(ISubject subject); 21 }
上述是介面。下面定義父類基類
1 /** 2 * 目標基類/父類 3 */ 4 public class BaseSubject implements ISubject { 5 /** 6 * 觀察者列表 7 */ 8 protected List<IObserver> observerList; 9 10 /** 11 * 建構函式 12 */ 13 public BaseSubject() { 14 observerList = new ArrayList<>(); 15 } 16 17 @Override 18 public void attach(IObserver observer) { 19 if (observer != null) { 20 observerList.add(observer); 21 } 22 } 23 24 @Override 25 public void detach(IObserver observer) { 26 if (observer != null) { 27 observerList.remove(observer); 28 } 29 } 30 31 @Override 32 public void notifyAllObserver() { 33 for (IObserver item : 34 observerList) { 35 item.update(this); 36 } 37 } 38 39 @Override 40 protected void finalize() throws Throwable { 41 for (IObserver item : 42 observerList) { 43 item.unsubscribe(); 44 } 45 observerList.clear(); 46 super.finalize(); 47 } 48 }
1 /** 2 * 觀察者基類/父類 3 */ 4 public class BaseObserver implements IObserver { 5 /** 6 * 目標物件 7 */ 8 protected ISubject subject; 9 10 /** 11 * 建構函式 12 */ 13 public BaseObserver() { 14 this.subject = null; 15 } 16 17 /** 18 * 建構函式 19 * @param subject 目標 20 */ 21 public BaseObserver(ISubject subject) { 22 this.subject = null; 23 subscribe(subject); 24 } 25 26 @Override 27 public void subscribe(ISubject subject) { 28 if (subject != null) { 29 this.subject = subject; 30 } 31 if (this.subject != null) { 32 this.subject.attach(this); 33 } 34 } 35 36 @Override 37 public void unsubscribe() { 38 if (this.subject != null) { 39 this.subject.detach(this); 40 } 41 } 42 43 @Override 44 public void update(ISubject subject) { 45 if (subject == this.subject) { 46 // 自己的業務 47 } 48 } 49 50 @Override 51 protected void finalize() throws Throwable { 52 unsubscribe(); 53 this.subject = null; 54 super.finalize(); 55 } 56 }
上述是基類/父類,後續再繼承各自的父類,進行實際業務的開展。
【實際業務的程式碼以及測試,這裡不寫了】
特別說明: 在不考慮效率的情況下,上述程式碼可以了。 但更多的時候,更多業務和資源,不允許不限制使用。 說簡單點,在上述的情況下,需要做一個資源優化(比如,重複重新整理、頻繁重新整理、佔用資源過多如何處理、推或拉的效率問題)。這個取決於業務本身。 再比如: 1、需要觀察多個目標,是觀察者模式1對多關係的升級擴充套件 2、更新協議-推拉模型的選定或混用 3、封裝複雜的更新語義