目錄
- 前言
- 概念
- 你有過這樣的問題嗎?
- 詳細介紹
- 原理:
- 應用場景:
- 實現方式:
- 類圖
- 代碼
- 問題回答
- 監聽,為什么叫監聽,具體代碼是哪
- 觀察者模式的需求衍變過程
- 觀察者是為什么是行為型
- 總結:
前言
????在軟件設計中,對象之間的通信是非常常見的情況。然而,當對象之間的通信過于緊密,可能會導致代碼的耦合度增加,使得系統難以維護和擴展。為了解決這個問題,觀察者模式應運而生。本文將介紹觀察者模式的原理、應用場景以及實現方式,并通過圖、代碼和例子進行詳細說明。
概念
????觀察者模式通過定義一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象,當主題對象發生變化時,會自動通知所有觀察者對象進行相應的更新操作。
你有過這樣的問題嗎?
- 概念中說“多個觀察者對象同時監聽某一個主題對象”,什么叫監聽,監聽是被動的還是主動的?在代碼中哪塊體現監聽了?
- 觀察者模式的需求是如何演變的?
- 觀察者模式屬于行為型,為什么呢?行為型有什么特點嗎?
- 觀察者模式應用場景有哪些?有什么不足嗎?
帶著類似的問題,看下面的內容,文章的最后也會對這些問題一一回答
詳細介紹
原理:
????觀察者模式由兩個核心角色組成:主題(Subject)和觀察者(Observer)。主題對象維護一個觀察者列表(有個容器用來放觀察者),當主題對象的狀態發生變化時,會遍歷觀察者列表,依次通知每個觀察者進行相應的更新操作。觀察者對象則通過注冊到主題對象上,以接收主題對象的通知。
應用場景:
觀察者模式在許多實際應用中都有廣泛的應用,例如:
-
消息訂閱和發布系統:主題對象充當消息發布者,觀察者對象充當消息訂閱者。當發布者發布新消息時,訂閱者會收到通知并進行相應的處理。
-
GUI開發:主題對象可以是用戶界面組件,觀察者對象可以是與該組件相關的其他組件。當用戶界面組件發生變化時,其他組件可以及時更新自身的狀態。
-
股票市場監控系統:主題對象可以是股票市場,觀察者對象可以是投資者。當股票市場行情發生變化時,投資者可以及時了解到最新的行情。
實現方式:
類圖
代碼
下面通過一個簡單的示例來演示觀察者模式的實現。
- 首先,我們定義主題接口(Subject),包含注冊觀察者、移除觀察者和通知觀察者的方法。
public interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}
- 然后,我們定義觀察者接口(Observer),包含接收通知并進行更新操作的方法。
public interface Observer {void update();
}
- 接下來,我們實現具體的主題類(ConcreteSubject),并在該類中實現注冊觀察者、移除觀察者和通知觀察者的方法。
public class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update();}}// 其他業務邏輯...
}
- 最后,我們實現具體的觀察者類(ConcreteObserver),并在該類中實現接收通知并進行更新操作的方法。
public class ConcreteObserver implements Observer {@Overridepublic void update() {// 執行更新操作...}
}
????通過以上代碼,我們可以看到,主題對象和觀察者對象之間并沒有直接的耦合關系,它們通過接口進行通信,實現了松耦合的對象間通信。
問題回答
監聽,為什么叫監聽,具體代碼是哪
????在觀察者模式中,觀察者對象通過注冊(或訂閱)的方式來監聽某一個主題對象。這個監聽的過程在代碼中體現在觀察者對象注冊到主題對象的觀察者列表中。
????具體地,主題對象通常會提供一些方法,例如attach(observer)和detach(observer),用于觀察者對象的注冊和注銷。當主題對象的狀態發生變化時,它會遍歷觀察者列表,并調用每個觀察者對象的相應方法,通知它們狀態的變化。
????關于為什么稱之為"監聽",這是因為在觀察者模式中,觀察者對象并不需要主動去輪詢或查詢主題對象的狀態,而是被動地接收主題對象的通知。觀察者對象通過注冊到主題對象上,就像是在"監聽"主題對象的狀態變化。
????觀察者對象并沒有主動去聽的動作,但它們被動地接收主題對象的通知,從而實現了對主題對象狀態變化的監聽。這種被動的接收通知的行為,可以理解為觀察者對象在"監聽"主題對象。
觀察者模式的需求衍變過程
故事背景:
????老板回來,前臺秘書發通知消息給正在玩的同事們(前提是,同事提前在秘書那“注冊”過–“老板來了通知我一下”),收到秘書的通知后,同事們各自采取行動
宏觀
????最初的通知者和觀察者是明確知道對方的存在的,但是在經過一次次的優化后觀察者和通知者都不知道對方具體存在只知曉一個接口或者抽象類,這里就是在一對多通知的時候使用這種抽象的好處,不需要知道具體的通知者和觀察者。
微觀:
1.雙向耦合:
????開始有三個類:前臺秘書類,看股票同事類,客戶端,此時的前臺秘書類與觀察者類相互耦合,前臺秘書類要增加觀察者、觀察者需要前臺的的狀態。
需要解決的問題是:前臺秘書類與觀察者類相互耦合。
2.解耦
????增加抽象的觀察者,增加了看NBA的同事,看股票的同事與看NBA 的同事繼承抽象觀察者。前臺秘書類中與具體的觀察者耦合的地方都改成了抽象觀察者。存在的問題是:具體的觀察者不應該依賴具體的主題,而是需要一個抽象的通知者。如果前臺有事來不及通知,那么通知誰來做?前臺不想通知某位同事,需要有移除方法進行支持。
3.觀察者模式
????觀察者模式的作用是在解耦合,讓耦合的雙方都依賴抽象,而不是依賴于具體。從而使得各自的變化都不會影響另一邊的變化。
如果觀察者是風馬牛不相及的類,使用接口更加合適。
觀察者模式的不足:
????抽象通知者依賴抽象觀察者,應該由客戶端決定通知誰;并不是每個具體的觀察者都是更新方法。
事件與委托的實現
????看股票的觀察者類、看NBA 觀察者類 去掉了父類抽象觀察者,并將更新方法名改為自己合適的方法名字。抽象觀察者不要了,聲明EventHandler委托,在具體的統治者類增加委托事件-update。
觀察者是為什么是行為型
????觀察者模式是一種行為型設計模式,因為它關注的是對象之間的行為和交互,通過定義接口和松耦合的方式實現了對象之間的動態關聯。
????在觀察者模式中,被觀察者和觀察者之間通過定義接口進行通信,這就意味著它們之間可以有不同的行為。被觀察者負責維護觀察者的列表,并在狀態發生改變時通知觀察者。觀察者則負責定義在接收到通知時要執行的行為。
????觀察者模式的行為型特點還體現在它的實現方式上。在觀察者模式中,被觀察者和觀察者之間是松耦合的,它們之間的關聯是動態的,可以隨時添加或移除觀察者。這種靈活性使得觀察者模式非常適合在復雜的系統中處理對象之間的行為和交互。
????簡單一句話總結行為型設計模式特點:
????行為型模式的核心,都有一個類,把整個模式要做的事封裝在這個類的一個方法里執行。
????具體在觀察者模式中這個類是ConcreteObserver,具體是其中的構造方法。具體觀察者,只管要它要訂閱哪個主題,(this.subject=subject.)但是它不管訂閱的主題具體做什么事,進而實現了整個設計模式要實現的行為。
總結:
????觀察者模式通過定義一種一對多的依賴關系,實現了對象之間的松耦合通信。它能夠幫助我們構建可維護和可擴展的系統。在實際應用中,我們可以根據具體的需求進行靈活的擴展和定制。希望本文對你理解觀察者模式有所幫助。