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