




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
/kalenchen/archive/2007/05/21/1619498.aspx概述在軟件系統(tǒng)中,某些類型由于自身的邏輯,它具有兩個或多個維度的變化,那么如何應(yīng)對這種“多維度”的變化?如何利用面向?qū)ο蟮募夹g(shù)來使得該類型能夠輕松的沿著多個方向進行變化,而又不引入額外的復(fù)雜度?這就是要使用Bridge模式。意圖將抽象部分與實現(xiàn)部分分離,使它們都可以獨立的變化。結(jié)構(gòu)圖圖1Bridge模式結(jié)構(gòu)圖生活中的例子橋接模式將抽象部分與它的實現(xiàn)分離,使它們能夠獨立地變化。一個普通開關(guān)控制的電燈、電風(fēng)扇等等,都是橋接的例子。開關(guān)的目的是將設(shè)備打開或關(guān)閉。實際的開關(guān)可以是簡單的雙刀拉鏈開關(guān),也可以是調(diào)光開關(guān)。圖2使用電子開關(guān)例子的橋接對象圖橋接模式解說在創(chuàng)建型模式里面,曾提到過抽象與實現(xiàn),抽象不應(yīng)該依賴于具體實現(xiàn)細(xì)節(jié),實現(xiàn)細(xì)節(jié)應(yīng)該依賴于抽象??聪旅孢@幅圖:圖3抽象不應(yīng)該依賴于實現(xiàn)細(xì)節(jié)在這種情況下,如果抽象B穩(wěn)定,而實現(xiàn)細(xì)節(jié)b變化,這時用創(chuàng)建型模式來解決沒有問題。但是如果抽象B也不穩(wěn)定,也是變化的,該如何解決?這就要用到Bridge模式了。我們?nèi)匀挥萌罩居涗浌ぞ哌@個例子來說明Bridge模式?,F(xiàn)在我們要開發(fā)一個通用的日志記錄工具,它支持?jǐn)?shù)據(jù)庫記錄DatabaseLog和文本文件記錄FileLog兩種方式,同時它既可以運行在.NET平臺,也可以運行在Java平臺上。根據(jù)我們的設(shè)計經(jīng)驗,應(yīng)該把不同的日志記錄方式分別作為單獨的對象來對待,并為日志記錄類抽象出一個基類Log出來,各種不同的日志記錄方式都繼承于該基類:圖4Log類結(jié)構(gòu)圖實現(xiàn)代碼如下:publicabstractclassLog...{publicabstractvoidWrite(stringlog);}publicclassDatabaseLog:Log...{publicoverridevoidWrite(stringlog)...{// LogDatabase}}publicclassTextFileLog:Log...{publicoverridevoidWrite(stringlog)...{// LogTextFile}}另外考慮到不同平臺的日志記錄,對于操作數(shù)據(jù)庫、寫入文本文件所調(diào)用的方式可能是不一樣的,為此對于不同的日志記錄方式,我們需要提供各種不同平臺上的實現(xiàn),對上面的類做進一步的設(shè)計得到了下面的結(jié)構(gòu)圖:實現(xiàn)代碼如下:publicclassNDatabaseLog:DatabaseLog...{publicoverridevoidWrite(stringlog)...{// (.NET平臺)LogDatabasepublicclassJDatabaseLog:DatabaseLog...{publicoverridevoidWrite(stringlog)...{// (Java平臺)LogDatabase}}publicclassNTextFileLog:TextFileLog...{publicoverridevoidWrite(stringlog)...{//......(.NET平臺)LogTextFile}}publicclassJTextFileLog:TextFileLog...{publicoverridevoidWrite(stringlog)...{// (Java平臺)LogTextFile}}現(xiàn)在的這種設(shè)計方案本身是沒有任何錯誤的,假如現(xiàn)在我們要引入一種新的xml文件的記錄方式,則上面的類結(jié)構(gòu)圖會變成:如圖中藍(lán)色部分所示,我們新增加了一個繼承于Log基類的子類,而沒有修改其它的子類,這樣也符合了開放-封閉原則。如果我們引入一種新的平臺,比如說我們現(xiàn)在開發(fā)的日志記錄工具還需要支持Borland平臺,此時該類結(jié)構(gòu)又變成了:同樣我們沒有修改任何東西,只是增加了兩個繼承于DatabaseLog和TextFileLog的子類,這也符合了開放-封閉原則。但是這樣的設(shè)計是脆弱的,仔細(xì)分析就可以發(fā)現(xiàn),它還是存在很多問題,首先它在遵循開放-封閉原則的同時,違背了類的單一職責(zé)原則,集即一個類只有一個引起它變化的原因,而這里引起Log類變化的原因卻有兩個,即日志記錄方式的變化和日志記錄平臺的變化;其次是重復(fù)代碼會很多,不同的日志記錄方式在不同的平臺上也會有一部分的代碼是相同的;再次是類的機構(gòu)過于復(fù)雜,繼承關(guān)系太多,難于維護;最后最致命的一點是擴展性太差。上面我們分析的變化只是沿著某一個方向,如果變化沿著日志記錄方式和不同的運行平臺兩個方向變化,我們會看到這個類的結(jié)構(gòu)會迅速變得龐大?,F(xiàn)在該是Bridge模式粉墨登場的時候了,我們需要解耦這兩個方面的變化,把它們之間的強耦合關(guān)系改成弱聯(lián)系。我們把日志記錄方式和不同平臺上的實現(xiàn)分別當(dāng)作兩個獨立的部分來對待,對于日志記錄方式,類結(jié)構(gòu)圖仍然是:現(xiàn)在我們引入另外一個抽象類ImpLog,它是日志記錄在不同平臺上實現(xiàn)的基類,結(jié)構(gòu)圖如下:實現(xiàn)代碼如下:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceBridgePattern...{/**////<summary>///功能:ImpLog類///編寫:Kalen_Chen///日期:2007年5月21日///</summary>publicabstractclassImpLog...{publicabstractvoidExecute(stringmsg);}}usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceBridgePattern...{/**////<summary>///功能:NImpLog類///編寫:Kalen_Chen///日期:2007年5月21日///</summary>publicclassNImpLog:ImpLog...{publicoverridevoidExecute(stringmsg)...{Console.WriteLine(".NET平臺:"+msg);}}}usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceBridgePattern...{/**////<summary>///功能:JImpLog類///編寫:Kalen_Chen///日期:2007年5月21日///</summary>publicclassJImpLog:ImpLog...{publicoverridevoidExecute(stringmsg)...{Console.WriteLine("Java平臺:"+msg);}}}這時對于日志記錄方式和不同的運行平臺這兩個類都可以獨立的變化了,我們要做的工作就是把這兩部分之間連接起來。那如何連接呢?在這里,Bridge使用了對象組合的方式,類結(jié)構(gòu)如下:實現(xiàn)代碼如下:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceBridgePattern...{/**////<summary>///功能:Log類///編寫:Kalen_Chen///日期:2007年5月21日///</summary>publicabstractclassLog...{protectedImpLogimplementor;publicImpLogImplementor...{set...{implementor=value;}}publicvirtualvoidWrite(stringlog)...{implementor.Execute(log);}}}usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceBridgePattern...{/**////<summary>///功能:DatabaseLog類///編寫:Kalen_Chen///日期:2007年5月21日///</summary>publicclassDatabaseLog:Log...{publicoverridevoidWrite(stringlog)...{implementor.Execute(log);usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceBridgePattern...{/**////<summary>///功能:TextFileLog類///編寫:Kalen_Chen///日期:2007年5月21日///</summary>publicclassTextFileLog:Log...{publicoverridevoidWrite(stringlog)...{implementor.Execute(log);}}}可以看到,通過對象組合的方式,Bridge模式把兩個角色之間的繼承關(guān)系改為了耦合的關(guān)系,從而使這兩者可以從容自若的各自獨立的變化,這也是Bridge模式的本意。再來看一下客戶端如何去使用:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceBridgePattern...{/**////<summary>///功能:客戶端調(diào)用///編寫:Kalen_Chen///日期:2007年5月21日///</summary>classProgram...{staticvoidMain(string[]args)...{//.NET平臺下的DatabaseLogLogdblog=newDatabaseLog();dblog.Implementor=newNImpLog();dblog.Write("DatabaseLog");//Java平臺下的TextFileLogLogtxtlog=newTextFileLog();txtlog.Implementor=newJImpLog();txtlog.Write("TextFileLog");Console.ReadLine();}}}可能有人會擔(dān)心說,這樣不就又增加了客戶程序與具體日志記錄方式之間的耦合性了嗎?其實這樣的擔(dān)心是沒有必要的,因為這種耦合性是由于對象的創(chuàng)建所帶來的,完全可以用創(chuàng)建型模式卻解決。最后我們再來考慮一個問題,為什么Bridge模式要使用對象組合的方式而不是用繼承呢?如果采用繼承的方式,則Log類,ImpLog類都為接口,類結(jié)構(gòu)圖如下:實現(xiàn)代碼如下:publicclassNDatabaseLog:DatabaseLog,IImpLog...{// }publicclassJDatabaseLog:DatabaseLog,IImpLog...{// }publicclassNTextFileLog:TextFileLog,IImpLog...{// publicclassJTextFileLog:TextFileLog,IlmpLog...{//......}如上圖中藍(lán)色的部分所示,它們既具有日志記錄方式特性,也具有接口IImpLog特性,它已經(jīng)違背了面向?qū)ο笤O(shè)計原則中類的單一職責(zé)原則,一個類應(yīng)當(dāng)僅有一個引起它變化的原因。所以采用Bridge模式往往是比采用多繼承更好的方案。說到這里,大家應(yīng)該對Bridge模式有一些認(rèn)識了吧?如果在開發(fā)中遇到有兩個方向上縱橫交錯的變化時,應(yīng)該能夠想到使用Bridge模式,當(dāng)然了,有時候雖然有兩個方向上的變化,但是在某一個方向上的變化并不是很劇烈的時候,并不一定要使用Bridge模式。實現(xiàn)要點及效果<!--[if!supportLists]-->1. <!--[endif]-->Bridge模式使用“對象間的組合關(guān)系”解耦了抽象和實現(xiàn)之間固有的綁定關(guān)系,使得抽象和實現(xiàn)可以沿著各自的維度來變化。<!--[if!supportLists]-->2. <!--[endif]-->所謂抽象和實現(xiàn)沿著各自維度的變化,即“子類化”它們,得到各個子類之后,便可以任意它們,從而獲得不同平臺上的不同型號。<!--[if!supportLists]-->3. <!--[endif]-->Bridge模式有時候類似于多繼承方案,但是多繼承方案往往違背了類的單一職責(zé)原則(即一個類只有一個變化的原因),復(fù)用性比較差。Bridge模式是比多繼承方案更好的解決方法。<!--[if!supportLists]--
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 大學(xué)通識教育的課程設(shè)置優(yōu)化策略
- 呼吸器官(教學(xué)設(shè)計)-2024-2025學(xué)年科學(xué)三年級上冊人教鄂教版
- 二零二五年度解除勞動合同提前通知員工安置合同
- 二零二五年度食用油品牌授權(quán)及銷售合同協(xié)議
- 2025年度醫(yī)院安全保衛(wèi)管理合同范本
- 旅游景區(qū)開發(fā)貸款居間協(xié)議
- 2025年度草原承包合同-草原生態(tài)環(huán)境保護與生態(tài)移民項目協(xié)議
- 二零二五年度農(nóng)產(chǎn)品貼牌加工與冷鏈物流服務(wù)協(xié)議
- Unit 3 Travel Digging in 合成詞 教學(xué)設(shè)計-2024-2025學(xué)年高中英語滬外版(2020)必修第一冊
- 二零二五年度礦山股份合作協(xié)議書:礦山土地開發(fā)利用與補償協(xié)議
- MySQL數(shù)據(jù)庫項目式教程完整版課件全書電子教案教材課件(完整)
- 藥品生產(chǎn)質(zhì)量管理工程完整版課件
- 職業(yè)衛(wèi)生教學(xué)課件生物性有害因素所致職業(yè)性損害
- 降“四高”健康教育課件
- 心理評估與診斷簡介
- 五十鈴、豐田全球化研究
- 新公務(wù)員體檢表
- 地下暗挖頂管及水下作業(yè)工程專項施工方案
- 讓孩子變成學(xué)習(xí)的天使——由《第56號教室的奇跡》讀書分享
- 安全風(fēng)險評價風(fēng)險矩陣法
- 球泡檢驗標(biāo)準(zhǔn)
評論
0/150
提交評論