<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                32.3 觀察者模式VS責任鏈模式 為什么要把觀察者模式和責任鏈模式放在一起對比呢?看起來這兩個模式沒有太多的相似性,真沒有嗎?回答是有。我們在觀察者模式中也提到了觸發鏈(也叫做觀察者鏈)的問題,一個具體的角色既可以是觀察者,也可以是被觀察者,這樣就形成了一個觀察者鏈。這與責任鏈模式非常類似,它們都實現了事務的鏈條化處理,比如說在上課的時候你睡著了,打鼾聲音太大,蓋過了老師講課聲音,老師火了,捅到了校長這里,校長也處理不了,然后告狀給你父母,于是你的魔鬼日子來臨了,這是責任鏈模式,老師、校長、父母都是鏈中的一個具體角色,事件(你睡覺)在鏈中傳遞,最終由一個具體的節點來處理,并將結果反饋給調用者(你挨揍了)。那什么是觸發鏈?你還是在課堂上睡覺,還是打鼾聲音太大,老師火了,但是老師掏出個擴音器來講課,于是你睡不著了,同時其他同學的耳朵遭殃了,這就是觸發鏈,其中老師既是觀察者(相對你)也是被觀察者(相對其他同學),事件從“你睡覺”到老師這里轉化為“擴音器放大聲音”,這也是一個鏈條結構,但是鏈結構中傳遞的事件改變了。 我們還是以一個具體的例子來說明兩者的區別,DNS協議相信大家都聽說過,只要在“網絡設置”中設置一個DNS服務器地址就可以把我們需要的域名翻譯成IP地址。DNS協議還是比較簡單的,傳遞過去一個域名以及記錄標志(比如是要A記錄還是要MX記錄),DNS就開始查找自己的記錄樹,找到后把IP地址反饋給請求者。我們可以在Windows操作系統中了解一下DNS解析過程,在DOS窗口下輸入nslookup命令后,結果如圖32-6所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036e2208b.jpg) 圖32-6 DNS服務器解析域名 我們的意圖就是要DNS服務器192.168.10.1解析出www.xxx.com.cn的IP地址,DNS服務器是如何工作的呢?圖32-6中的192.168.10.1這個DNS Server存儲著全球的域名和IP之間的對應關系嗎?不可能,目前全球的域名數量是1.7億個,如此龐大的數字,每個DNS服務器都存儲一份,還怎么快速響應?DNS解析的響應時間一般都是毫秒級別的,如此高的性能要求還怎么讓DNS服務器遍地開花呢?而且域名變更非常頻繁,數據讀寫的量也非常大,不可能每個DNS服務器都保留這1.7億數據,那么是怎么設計的呢?DNS協議還是很聰明的,它規定了每個區域的DNS服務器(Local DNS)只保留自己區域的域名解析,對于不能解析的域名,則提交上級域名解析器解析,最終由一臺位于美國洛杉磯的頂級域名服務器進行解析,返回結果。很明顯這是一個事務的鏈結構處理,我們使用兩種模式來實現該解析過程。 32.3.1 責任鏈模式實現DNS解析過程 本小節我們用責任鏈模式來實現DNS解析過程。首先我們定義一下業務場景,這里有三個DNS服務器:上海DNS服務器(區域服務器)、中國頂級DNS服務器(父服務器)、全球頂級DNS服務器,其示意圖如圖32-7所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036e397fb.jpg) 圖32-7 DNS解析示意圖 假設有請求者發出請求,由上海DNS進行解析,如果能夠解析,則返回結果,若不能解析,則提交給父服務器(中國頂級DNS)進行解析,若還不能解析,則提交到全球頂級DNS進行解析,若還不能解析呢?那就返回該域名無法解析。確實,這與責任鏈模式非常相似,我們把這一過程抽象一下,類圖如圖32-8所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036e4d62c.jpg) 圖32-8 責任鏈模式實現DNS解析的類圖 我們來解釋一下類圖,Recorder是一個BO對象,它記錄DNS服務器解析后的結果,包括域名、IP地址、屬主(即由誰解析的),除此之外還有getter/setter方法。DnsServer抽象類中的resolve方法是一個基本方法,每個DNS服務器都必須擁有該方法,它對DNS進行解析,如何解析呢?具體是由echo方法來實現的,每個DNS服務器獨自實現。類圖還是比較簡單的,我們首先看一下解析記錄Recorder類,如代碼清單32-31所示。 代碼清單32-31 解析記錄 public?class?Recorder?{ ?????//域名 ?????private?String?domain; ?????//IP地址 ?????private?String?ip; ?????//屬主 ?????private?String?owner; ?????public?String?getDomain()?{ ?????????????return?domain; ?????} ?????public?void?setDomain(String?domain)?{ ?????????????this.domain?=?domain; ?????} ?????public?String?getIp()?{ ?????????????return?ip; ?????} ?????public?void?setIp(String?ip)?{ ?????????????this.ip?=?ip; ?????} ?????public?String?getOwner()?{ ?????????????return?owner; ?????} ?????public?void?setOwner(String?owner)?{ ?????????????this.owner?=?owner; ?????} ?????//輸出記錄信息 ?????@Override ?????public?String?toString(){ ?????????????String?str=?"域名:"?+?this.domain; ?????????????str?=?str?+?"\nIP地址:"?+?this.ip; ?????????????str?=?str?+?"\n解析者:"?+?this.owner; ?????????????return?str; ?????} } 為什么要覆寫toString方法呢?是為了打印展示的需要,可以直接把Recorder的信息打印出來。我們再來看抽象域名服務器,如代碼清單32-32所示。 代碼清單32-32 抽象域名服務器 public?abstract?class?DnsServer?{ ?????//上級DNS是誰 ?????private?DnsServer?upperServer; ?????//解析域名 ?????public?final?Recorder?resolve(String?domain){ ?????????????Recorder?recorder=null; ?????????????if(isLocal(domain)){//是本服務器能解析的域名 ?????????????????????recorder?=?echo(domain); ?????????????}else{//本服務器不能解析 ?????????????????????//提交上級DNS進行解析 ?????????????????????recorder?=?upperServer.resolve(domain); ?????????????} ?????????????return?recorder; ?????} ?????//指向上級DNS ?????public?void?setUpperServer(DnsServer?_upperServer){ ?????????????this.upperServer?=?_upperServer; ?????} ?????//每個DNS都有一個數據處理區(ZONE),檢查域名是否在本區中 ?????protected?abstract?boolean?isLocal(String?domain); ?????//每個DNS服務器都必須實現解析任務 ?????protected?Recorder?echo(String?domain){ ?????????????Recorder?recorder?=?new?Recorder(); ?????????????//獲得IP地址 ?????????????recorder.setIp(genIpAddress()); ?????????????recorder.setDomain(domain); ?????????????return?recorder; ?????} ?????//隨機產生一個IP地址,工具類 ?????private?String?genIpAddress(){ ?????????????Random?rand?=?new?Random(); ?????????????String?address?=?rand.nextInt(255)?+?"."?+?rand.nextInt(255)?+?"."+?rand.nextInt(255)?+?"."+?rand.nextInt(255); ?????????????return?address; ?????} } 在該類中有一個方法——genIpAddress方法——沒有在類圖中展現出來,它用于實現隨機生成IP地址,這是我們為模擬DNS解析場景而建立的一個虛擬方法,在實際的應用中是不可能出現的。抽象DNS服務器編寫完成,我們再來看具體的DNS服務器,先看上海的DNS服務器,如代碼清單32-33所示。 代碼清單32-33 上海DNS服務器 public?class?SHDnsServer?extends?DnsServer?{ ?????@Override ?????protected?Recorder?echo(String?domain)?{ ?????????????Recorder?recorder=?super.echo(domain); ?????????????recorder.setOwner("上海DNS服務器"); ?????????????return?recorder; ?????} ?????//定義上海的DNS服務器能處理的級別 ?????@Override ?????protected?boolean?isLocal(String?domain)?{ ?????????????return?domain.endsWith(".sh.cn"); ?????} } 為什么要覆寫echo方法?各具體的DNS服務器實現自己的解析過程,屬于個性化處理,它代表的是每個DNS服務器的不同處理邏輯。還要注意一下,我們在這里做了一個簡化處理,所有以".sh.cn"結尾的域名都由上海DNS服務器解析。其他的中國頂級DNS和全球頂級DNS實現過程類似,如代碼清單32-34、32-35所示。 代碼清單32-34 中國頂級DNS服務器 public?class?ChinaTopDnsServer?extends?DnsServer?{ ?????@Override ?????protected?Recorder?echo(String?domain)?{ ????????????????Recorder?recorder?=?super.echo(domain); ????????????????recorder.setOwner("中國頂級DNS服務器"); ????????????????return?recorder; ?????} ?????@Override ?????protected?boolean?isLocal(String?domain)?{ ????????????????return?domain.endsWith(".cn"); ?????} } 代碼清單32-35 全球頂級DNS服務器 public?class?TopDnsServer?extends?DnsServer?{ ?????@Override ?????protected?Recorder?echo(String?domain)?{ ?????????????Recorder?recorder?=?super.echo(domain); ?????????????recorder.setOwner("全球頂級DNS服務器"); ?????????????return?recorder; ?????} ?????@Override ?????protected?boolean?isLocal(String?domain)?{ ?????????????//所有的域名最終的解析地點 ?????????????return?true; ?????} } 所有的DNS服務器都準備好了,下面我們寫一個客戶端來模擬一下IP地址是怎么解析的,如代碼清單32-36所示。 代碼清單32-36 場景類 public?class?Client?{ ?????public?static?void?main(String[]?args)?throws?Exception?{ ?????????????//上海域名服務器 ?????????????DnsServer?sh?=?new?SHDnsServer(); ?????????????//中國頂級域名服務器 ?????????????DnsServer?china?=?new?ChinaTopDnsServer(); ?????????????//全球頂級域名服務器 ?????????????DnsServer?top?=?new?TopDnsServer(); ?????????????//定義查詢路徑 ?????????????china.setUpperServer(top); ?????????????sh.setUpperServer(china); ?????????????//解析域名 ?????????????System.out.println("=====域名解析模擬器====="); ?????????????while(true){ ?????????????????????System.out.print("\n請輸入域名(輸入N退出):"); ?????????????????????String?domain?=?(new?BufferedReader(new?InputStreamReader?(System.in))).readLine(); ?????????????????????if(domain.equalsIgnoreCase("n")){ ?????????????????????????????return; ?????????????????????} ?????????????????????Recorder?recorder?=?sh.resolve(domain); ?????????????????????System.out.println("----DNS服務器解析結果----"); ?????????????????????System.out.println(recorder);??????????????? ?????????????} ?????} } 我們來模擬一下,運行結果如下所示: =====域名解析模擬器===== 請輸入域名(輸入N退出):www.xxx.sh.cn ----DNS服務器解析結果---- 域名:www. xxx.sh.cn IP地址:69.224.162.154 解析者:上海DNS服務器 請輸入域名(輸入N退出):www. xxx.com.cn ----DNS服務器解析結果---- 域名:www. xxx.com.cn IP地址:51.28.66.140 解析者:中國頂級DNS服務器 請輸入域名(輸入N退出):www. xxx.com ----DNS服務器解析結果---- 域名:www. xxx.com IP地址:73.247.80.117 解析者:全球頂級DNS服務器 請輸入域名(輸入N退出):n 請注意看運行結果,以".sh.cn"結尾的域名確實由上海DNS服務器解析了,以".cn"結尾的域名由中國頂級DNS服務器解析了,其他域名都由全球頂級DNS服務器解析。這個模擬過程看起來很完整,它完全就是責任鏈模式的一個具體應用,把一個請求放置到鏈中的首節點,然后由鏈中的某個節點進行解析并將結果反饋給調用者。但是,我可以負責任地告訴你:這個解析過程是有缺陷的,什么缺陷?后面會說明。 32.3.2 觸發鏈模式實現DNS解析過程 上面說到使用責任鏈模式模擬DNS解析過程是有缺陷的,究竟有什么缺陷?大家是不是覺得這個解析過程很完美了,沒什么問題了?那說明你對DNS協議了解得還不太深入。我們來做一個實驗,在dos窗口下輸入nslookup命令,然后輸入多個域名,注意觀察返回值有哪些數據是相同的。可以看出,解析者都相同,都是由同一個DNS服務器解析的,準確地說都是由本機配置的DNS服務器做的解析。這與我們上面的模擬過程是不相同的,看看我們模擬的過程,對請求者來說,".sh.cn"是由區域DNS解析的,".com"卻是由全球頂級DNS解析的,與真實的過程不相同,這是怎么回事呢? 肯定地說,采用責任鏈模式模擬DNS解析過程是不完美的,或者說是有缺陷的,怎么來修復這個缺陷呢?我們先來看看真實的DNS解析過程,如圖32-9所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036e8989a.jpg) 圖32-9 真實的DNS解析示意圖 解析一個域名的完整路徑如圖32-9中的標號①~⑥所示,首先由請求者發送一個請求,然后由上海DNS服務器嘗試解析,若不能解析再通過路徑②轉發給中國頂級DNS進行解析,解析后的結果通過路徑⑤返回給上海DNS服務器,然后由上海DNS服務器通過路徑⑥返回給請求者。同樣,若中國頂級DNS不能解析,則通過路徑③轉由全球頂級DNS進行解析,通過路徑④把結果返回給中國頂級DNS,然后再通過路徑⑤返回給上海DNS。注意看標號⑥,不管一個域名最終由誰解析,最終反饋到請求者的還是第一個節點,也就是說首節點負責對請求者應答,其他節點都不與請求者交互,而只與自己的左右節點交互。實際上我們的DNS服務器確實是如此處理的,例如本機請求查詢一個www.abcdefg.com的域名,上海DNS服務器解析不到這個域名,于是提交到中國頂級DNS服務器,如果中國頂級DNS服務器有該域名的記錄,則找到該記錄,反饋到上海DNS服務器,上海DNS服務器做兩件事務處理:一是響應請求者,二是存儲該記錄,以備其他請求者再次查詢,這類似于數據緩存。 整個場景我們已經清晰,想想看,我們把請求者看成是被觀察者,它的行為或屬性變更通知了觀察者——上海DNS,上海DNS又作為被觀察者出現了自己不能處理的行為(行為改變),通知了中國頂級DNS,依次類推,這是不是一個非常標準的觸發鏈?而且還必須是同步的觸發,異步觸發已經在該場景中失去了意義(讀者可以想想為什么)。 分析了這么多,我們用觸發鏈來模擬DNS的解析過程,如圖32-10所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036e9c8e5.jpg) 圖32-10 觸發鏈模式實現DNS解析的類圖 與責任鏈模式很相似,僅僅多了一個Observable父類和Observer接口,但是在實現上這兩種模式有非常大的差異。我們先來解釋一下抽象DnsServer的作用。 ● 標示聲明 表示所有的DNS服務器都具備雙重身份:既是觀察者也是被觀察者,這很重要,它聲明所有的服務器都具有相同的身份標志,具有該標志后就可以在鏈中隨意移動,而無需固定在鏈中的某個位置(這也是鏈的一個重要特性)。 ● 業務抽象 方法setUpperServer的作用是設置父DNS,也就是設置自己的觀察者,update方法不僅僅是一個事件的處理者,也同時是事件的觸發者。 我們來看代碼,首先是最簡單的,Recorder類與責任鏈模式中的記錄相同,這里不再贅述。那我們就先看看該模式的核心抽象DnsServer,如代碼清單32-37所示。 代碼清單32-37 抽象DNS服務器 public?abstract?class?DnsServer?extends?Observable?implements?Observer?{ ?????//處理請求,也就是接收到事件后的處理 ?????public?void?update(Observable?arg0,?Object?arg1)?{ ?????????????Recorder?recorder?=?(Recorder)arg1; ?????????????//如果本機能解析 ?????????????if(isLocal(recorder)){ ?????????????????????recorder.setIp(genIpAddress()); ?????????????}else{//本機不能解析,則提交到上級DNS ?????????????????????responsFromUpperServer(recorder); ?????????????} ?????????????//簽名 ?????????????sign(recorder); ?????} ?????//作為被觀察者,允許增加觀察者,這里上級DNS一般只有一個 ?????public?void?setUpperServer(DnsServer?dnsServer){ ?????????????//先清空,然后再增加 ?????????????super.deleteObservers(); ?????????????super.addObserver(dnsServer); ?????} ?????//向父DNS請求解析,也就是通知觀察者 ?????private?void?responsFromUpperServer(Recorder?recorder){ ?????????????super.setChanged(); ?????????????super.notifyObservers(recorder); ?????} ?????//每個DNS服務器簽上自己的名字 ?????protected?abstract?void?sign(Recorder?recorder); ?????//每個DNS服務器都必須定義自己的處理級別 ?????protected?abstract?boolean?isLocal(Recorder?recorder); ?????//隨機產生一個IP地址,工具類 ?????private?String?genIpAddress(){ ?????????????Random?rand?=?new?Random(); ?????????????String?address?=?rand.nextInt(255)?+?"."?+?rand.nextInt(255)?+?"."+?rand.nextInt(255)?+?"."+?rand.nextInt(255); ?????????????return?address; ?????} } 注意看一下responseFromUpperServer方法,它只允許設置一個觀察者,因為一般的DNS服務器都只有一個上級DNS服務器。sign方法是簽名,這個記錄是由誰解析出來的,就由各個實現類獨自來實現。三個DnsServer的實現類都比較簡單,如代碼清單32-38、32-39、32-40所示。 代碼清單32-38 上海DNS服務器 public?class?SHDnsServer?extends?DnsServer?{ ?????@Override ?????protected?void?sign(Recorder?recorder)?{ ?????????????recorder.setOwner("上海DNS服務器"); ?????} ?????//定義上海的DNS服務器能處理的級別 ?????@Override ?????protected?boolean?isLocal(Recorder?recorder)?{ ?????????????return?recorder.getDomain().endsWith(".sh.cn"); ?????} } 代碼清單32-39 中國頂級DNS服務器 public?class?ChinaTopDnsServer?extends?DnsServer?{ ?????@Override ?????protected?void?sign(Recorder?recorder)?{ ?????????????recorder.setOwner("中國頂級DNS服務器"); ?????} ?????@Override ?????protected?boolean?isLocal(Recorder?recorder)?{ ?????????????return?recorder.getDomain().endsWith(".cn"); ?????} } 代碼清單32-40 全球頂級DNS服務器 public?class?TopDnsServer?extends?DnsServer?{ ?????@Override ?????protected?void?sign(Recorder?recorder)?{ ?????????????recorder.setOwner("全球頂級DNS服務器"); ?????} ????? ?????@Override ?????protected?boolean?isLocal(Recorder?recorder)?{ ?????????????//所有的域名最終的解析地點 ?????????????return?true; ?????} } 我們再建立一個場景類模擬一下DNS解析過程,如代碼清單32-41所示。 代碼清單32-41 場景類 public?class?Client?{ ?????public?static?void?main(String[]?args)?throws?Exception?{ ?????????????//上海域名服務器 ?????????????DnsServer?sh?=?new?SHDnsServer(); ?????????????//中國頂級域名服務器 ?????????????DnsServer?china?=?new?ChinaTopDnsServer(); ?????????????//全球頂級域名服務器 ?????????????DnsServer?top?=?new?TopDnsServer(); ?????????????//定義查詢路徑 ?????????????china.setUpperServer(top); ?????????????sh.setUpperServer(china); ?????????????//解析域名 ?????????????System.out.println("=====域名解析模擬器====="); ?????????????while(true){ ?????????????????????System.out.print("\n請輸入域名(輸入N退出):"); ?????????????????????String?domain?=?(new?BufferedReader(new?InputStreamReader?(System.in))).readLine(); ?????????????????????if(domain.equalsIgnoreCase("n")){ ?????????????????????????????return; ?????????????????????} ?????????????????????Recorder?recorder?=?new?Recorder(); ?????????????????????recorder.setDomain(domain); ?????????????????????sh.update(null,recorder); ?????????????????????System.out.println("----DNS服務器解析結果----"); ?????????????????????System.out.println(recorder);??????????????? ?????????????} ?????} } 與責任鏈模式中的場景類很相似。讀者請注意sh.update(null,recorder)這句代碼,這是我們虛擬了觀察者觸發動作,完整的做法是把場景類作為一個被觀察者,然后設置觀察者為上海DNS服務器,再進行測試,其結果完全相同,我們這里為減少代碼量采用了簡化處理,有興趣的讀者可以擴充實現。 我們來看看運行結果如何,結果如下所示: =====域名解析模擬器===== 請輸入域名(輸入N退出):www.xxx.sh.cn ----DNS服務器解析結果---- 域名:www.xxx.sh.cn IP地址:197.15.34.227 解析者:上海DNS服務器 請輸入域名(輸入N退出):www.xxx.com.cn ----DNS服務器解析結果---- 域名:www.xxx.com.cn IP地址:201.177.148.99 解析者:上海DNS服務器 請輸入域名(輸入N退出):www.xxx.com ----DNS服務器解析結果---- 域名:www.xxx.com IP地址:251.41.14.230 解析者:上海DNS服務器 請輸入域名(輸入N退出):n 可以看出,所有的解析結果都是由上海DNS服務器返回的,這才是真正的DNS解析過程。如何知道它是由上海DNS服務器解析的還是由別的DNS服務器解析的呢?很好辦,把代碼拷貝過去,然后調試跟蹤一下就可以了。或者仔細看看代碼,理解一下代碼邏輯也可以非常清楚地知道它是如何解析的。 再仔細看一下我們的代碼邏輯,上下兩個節點之間的關系很微妙,很有意思。 ● 下級節點對上級節點頂禮膜拜 比如我們輸入的這個域名www.xxx.com,上海域名服務器只知道它是由父節點(中國頂級DNS服務器)解析的,而不知道父節點把該請求轉發給了更上層節點(全球頂級DNS服務器),也就是說下級節點關注的是上級節點的響應,只要是上級反饋的結果就認為是上級的。www.xxx.com這個域名最終是由最高節點(全球頂級DNS服務器)解析的,它把解析結果傳遞給第二個節點(中國頂級DNS服務器)時的簽名為“全球頂級DNS服務器”,而第二個節點把請求傳遞給首節點(上海DNS服務器)時的簽名被修改為“中國頂級DNS服務器”。所有從上級節點反饋的響應都認為是上級節點處理的結果,而不追究到底是不是真的是上級節點處理的。 ● 上級節點對下級節點絕對信任 上級節點只對下級節點負責,它不關心下級節點的請求從何而來,只要是下級發送的請求就認為是下級的。還是以www.xxx.com域名為例,當最高節點(全球頂級DNS服務器)獲得解析請求時,它認為這個請求是誰的?當然是第二個節點(中國頂級DNS服務器)的,否則它也不會把結果反饋給它,但是這個請求的源頭卻是首節點(上海DNS服務器)的。 32.3.3 小結 通過對DNS解析過程的實現,我們發現觸發鏈和責任鏈雖然都是鏈結構,但是還是有區別的。 ● 鏈中的消息對象不同 從首節點開始到最終的尾節點,兩個鏈中傳遞的消息對象是不同的。責任鏈模式基本上不改變消息對象的結構,雖然每個節點都可以參與消費(一般是不參與消費),類似于“雁過拔毛”,但是它的結構不會改變,比如從首節點傳遞進來一個String對象或者Person對象,不會到鏈尾的時候成了int對象或者Human對象,這在責任鏈模式中是不可能的,但是在觸發鏈模式中是允許的,鏈中傳遞的對象可以自由變化,只要上下級節點對傳遞對象了解即可,它不要求鏈中的消息對象不變化,它只要求鏈中相鄰兩個節點的消息對象固定。 ● 上下節點的關系不同 在責任鏈模式中,上下節點沒有關系,都是接收同樣的對象,所有傳遞的對象都是從鏈首傳遞過來,上一節點是什么沒有關系,只要按照自己的邏輯處理就成。而觸發鏈模式就不同了,它的上下級關系很親密,下級對上級頂禮膜拜,上級對下級絕對信任,鏈中的任意兩個相鄰節點都是一個牢固的獨立團體。 ● 消息的分銷渠道不同 在責任鏈模式中,一個消息從鏈首傳遞進來后,就開始沿著鏈條向鏈尾運動,方向是單一的、固定的;而觸發鏈模式則不同,由于它采用的是觀察者模式,所以有非常大的靈活性,一個消息傳遞到鏈首后,具體怎么傳遞是不固定的,可以以廣播方式傳遞,也可以以跳躍方式傳遞,這取決于處理消息的邏輯。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看