摘要:實際上,設計模式就是通過面向對象的特性,將這些角色解耦觀察者模式本質上就是一種訂閱發布的模型,從邏輯上來說就是一對多的依賴關系。在添加一個觀察者時,把被主題被觀察者對象以構造函數的形式給傳入了觀察者。
每個角色都對應這一個類,比如觀察者模式,觀察者對應著觀察者類,被觀察者對應著被觀察者類。實際上,設計模式就是通過面向對象的特性,將這些角色解耦
觀察者模式本質上就是一種訂閱 / 發布的模型,從邏輯上來說就是一對多的依賴關系。什么意思呢?好比是一群守衛盯著一個囚犯,只要囚犯一有異動,守衛就必須馬上采取行動(也有可能是更新狀態,本質上也是一種行動),那么守衛就是觀察者,囚犯就是被觀察者
在一個系統中,實現這種一對多的而且之間有一定關聯的邏輯的時候,由于需要保持他們之間的協同關系,所以最簡便的方法是采用緊耦合,把這些對象綁定到一起。但是這樣一來,一旦有擴展或者修改的時候,開發人員所面對的難度非常大,而且很容易造成Bug。那么觀察者模式就解決了這么一個問題,在保持一系列觀察者和被觀察者對象協同工作的同時,把解耦了它們
Coding抽象觀察者角色類
public interface Observer { // 更新接口 public void update(); }
具體觀察者角色類
public class ConcreteObserver implements Observer { // 觀察者的狀態 private String observerState = "Initial"; // 觀察者初始狀態,會隨著被觀察者變化而變化 private String name; // 觀察者名稱,用于標記不同觀察者 private Subject concreteSubject; // 構造觀察者,并傳入被主題對象,以及標識該觀察者名稱 public ConcreteObserver(Subject concreteSubject, String name) { this.concreteSubject = concreteSubject; this.name = name; System.out.println("我是觀察者" + name +", 我的狀態是" + observerState); } // 觀察者狀態隨主題主題改變 public void update() { observerState = concreteSubject.SubjectState; System.out.println("我是觀察者" + name +", 我的狀態是" + observerState); } }
抽象主題角色類
import java.util.List; public abstract class Subject { // 用來保存注冊的觀察者對象 Listlist = null; String SubjectState; // 注冊觀察者對象 public void attach(Observer observer){}; //刪除觀察者對象 public void detach(Observer observer){}; // 通知所有注冊的觀察者對象 public void nodifyObservers(String newState){}; }
具體主題角色類
import java.util.ArrayList; import java.util.List; public class ConcreteSubject extends Subject { private Listlist = new ArrayList (); public String SubjectState; // 注冊觀察者對象 public void attach(Observer observer) { list.add(observer); System.out.println("Attached an observer"); } //刪除觀察者對象 public void detach(Observer observer){ list.remove(observer); } // 通知所有注冊的觀察者對象 public void nodifyObservers(String newState) { for(Observer observer : list) { observer.update(); } } }
客戶端
public class Client { public static void main(String[] args) { // 創建主題對象 Subject concreteSubject = new ConcreteSubject(); concreteSubject.attach(new ConcreteObserver(concreteSubject, "安倍晴明")); concreteSubject.attach(new ConcreteObserver(concreteSubject, "神樂")); concreteSubject.attach(new ConcreteObserver(concreteSubject, "源博雅")); concreteSubject.SubjectState = "結界突破!"; concreteSubject.nodifyObservers(concreteSubject.SubjectState); } }
運行結果
我是觀察者安倍晴明, 我的狀態是Initial Attached an observer 我是觀察者神樂, 我的狀態是Initial Attached an observer 我是觀察者源博雅, 我的狀態是Initial Attached an observer 我是觀察者安倍晴明, 我的狀態是結界突破! 我是觀察者神樂, 我的狀態是結界突破! 我是觀察者源博雅, 我的狀態是結界突破!觀察者模式關鍵點
在主題(被觀察者)中,定義了一個集合用來存放觀察者,編寫了注冊attach()和移除detach()觀察者的方法,這體現了一對多的關系,也提供了可以控制觀察者的方式
關鍵點1:每個觀察者需要被保存到主題(被觀察者)的集合中,并且被觀察者提供添加和刪除的方式
觀察者和被觀察者之間的交互活動。在添加一個觀察者時,把被主題(被觀察者)對象以構造函數的形式給傳入了觀察者。最后主題(被觀察者)執行nodifyObservers()方法,觸發所有觀察者的update()方法以更新狀態
關鍵點2:被主題(被觀察者)把自己傳給觀察者,當狀態改變后,通過遍歷或循環的方式逐個通知列表中的觀察者
但這里有個問題,主題(被觀察者)是通過構造函數參數的形式,傳給觀察者的,而觀察者對象時被attach()到主題(被觀察者)的list中
關鍵點3:雖然解耦了觀察者和主題(被觀察者)的依賴,讓各自的變化不大影響另一方的變化,但是這種解耦并不徹底,沒有完全解除兩者之間的耦合
關鍵點4:在事件中,訂閱者和發布者之間是通過把事件處理程序綁定到委托,并不是把自身傳給對方。所以解決了觀察者模式中不完全解耦的問題
委托,事件,和觀察者模式之間的關系觀察者模式,必然涉及到2委托和事件這兩種類型
委托委托就是可把方法當做另一個方法參數來傳遞,需要注意方法簽名。委托可以看做是方法的抽象,也就是方法的“類”,一個委托的實例可以是一個或者多個方法。我們可以通過+=或者-=把方法綁定到委托或者從委托移除
事件事件是一種特殊的委托。首先事件也是委托,只是在聲明事件的時候,需要加上event,如果你用reflector去看一個事件,你會發現里面就3樣東西,一個Add_xxxx方法,一個Remove_xxx方法,一個委托。和上面所定義主題(被觀察者)時的注冊attach()和移除detach()有些聯系
.Net事件機制實際上.Net的事件機制就是觀察者模式的一種體現,并且是利用委托來實現。本質上事件就是一種訂閱-發布模型也就是觀察者模式,這種機制中包含2個角色,一個是發布者,一個是訂閱者。發布者類也就類似于主題(被觀察者),發布者類包含事件和委托定義,以及其之間的關系,發布者類的對象調用事件通知其他訂閱者。而訂閱者類也就類似于觀察者,觀察者接受事件,并且提供處理的邏輯。也就是說,訂閱者對象(觀察者)中的方法會綁定到發布者(被觀察者)對象的委托中,一旦發布者(被觀察者)中事件被調用,發布者(被觀察者)就會調用委托中綁定的訂閱者(觀察者)的處理邏輯或者說是處理程序,這就是通過觀察者模式實現的事件
觀察者模式問答在普通的觀察者模式中,解耦并不徹底,那么在事件的發布訂閱模型中,解耦徹底嗎?為什么?
答案是肯定的。因為在事件中,訂閱者和發布者之間是通過把事件處理程序綁定到委托,并不是把自身傳給對方。所以解決了觀察者模式中不完全解耦的問題
通過委托綁定方法來實現觀察者模式,會不會有什么隱患?
有的,通過+=去把方法綁定到委托,很容易忘記-=。如果只綁定不移除,這個方法會一直被引用。我們知道GC去回收的時候,只會處理沒有被引用的對象,只要是還被引用的對象時不會被回收掉的。所以如果在長期不關閉的系統中(比如監控系統),大量的代碼使用+=而不-=,運行時間長以后有可能會內存溢出
事件,委托,觀察者模式之間的關系
委托是一種類型,事件是一種特殊的委托,觀察者模式是一種設計模式,事件的機制是觀察者模式的一種實現,其中訂閱者和發布者通過委托實現協同工作
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66508.html
摘要:三內置觀察者模式了解內置觀察者模式包內包含最基本的類與接口,這和上面的接口與接口很類似。根據具體的需求,如果內置的觀察者模式不能滿設計,那么我們可以像剛開始那樣自己實現一套觀察者模式。參考資料設計模式 一、了解觀察者模式 1.1 什么是觀察者模式 觀察者模式定義了對象之間的一對多依賴,這樣一來,當一個對象狀態改變時,它的所有依賴者都會收到通知并自動更新。 典型的問題比如報社,只要你是他...
摘要:觀察者模式的使用場景比如你微博關注了一個人,那么這個人發布的微博就會推送到你這。 Java設計模式之觀察者模式 一直想寫一篇學習觀察者模式的總結沒有契機,今天學習阻塞隊列的原理時候看到在實現生產者消費者的時候用到了通知模式,就是所謂的觀察者模式,正好順便整理一下。 1. 簡介 觀察者模式定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更...
摘要:為了幫助灰太狼擺脫被老婆平底鍋抽的悲劇,發起了解救灰太狼的行動,必須要知道觀察者模式。持有觀察者對象的集合。設計模式源碼下載 相信大家都有看過《喜洋洋與灰太狼》,說的是灰太狼和羊族的斗爭,而每次的結果都是灰太狼一飛沖天,伴隨著一句我還會回來的......。為灰太狼感到悲哀,抓不到羊,在家也被老婆平底鍋虐待。灰太狼為什么會這么背? 很簡單,灰太狼本身就有暴露行蹤的屬性,羊咩咩就能知曉灰太...
摘要:觀察者模式觀察者模式也可以成為發布訂閱模式,此模式是對象之間的模式,對象之間呈現一種一對多的關系。其中的一是被觀察者,多是觀察者,故被觀察者不能產生多個對象,只能有一個對象供觀察者觀察,所以在寫被觀察者的時候,需要使用到單例模式。 觀察者(Observer)模式 觀察者(Observer)模式 也可以成為發布訂閱模式,此模式是對象之間的模式,對象之間呈現一種一對多的關系。其中的一是被觀...
摘要:觀察者模式涉及的角色主題一對多中的一,持有數據,當數據更新時,通知已注冊的觀察者觀察者一對多中的多,接收主題數據做出響應舉個栗子一位媽媽主題有兩個孩子,取名為小愛和小冰觀察者。 概念 觀察者模式:定義了對象之間的一對多依賴,這樣一來,當一個對象狀態改變時,他的所有依賴者都會收到通知并自動更新。 showImg(https://segmentfault.com/img/bVbf0or?w...
閱讀 2761·2021-11-19 09:40
閱讀 5337·2021-09-27 14:10
閱讀 2111·2021-09-04 16:45
閱讀 1491·2021-07-25 21:37
閱讀 3005·2019-08-30 10:57
閱讀 2991·2019-08-28 17:59
閱讀 1063·2019-08-26 13:46
閱讀 1416·2019-08-26 13:27