亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

(第Ⅲ部分 結(jié)構(gòu)型模式篇) 第8章 橋接模式(Brid

系統(tǒng) 2297 0
——.NET設(shè)計模式系列之九
Terrylee 2006 2
概述
在軟件系統(tǒng)中,某些類型由于自身的邏輯,它具有兩個或多個維度的變化,那么如何應(yīng)對這種“多維度的變化”?如何利用面向?qū)ο蟮募夹g(shù)來使得該類型能夠輕松的沿著多個方向進行變化,而又不引入額外的復雜度?這就要使用 Bridge 模式。
意圖
將抽象部分與實現(xiàn)部分分離,使它們都可以獨立的變化。 [GOF 《設(shè)計模式》 ]
結(jié)構(gòu)圖
1 Bridge 模式結(jié)構(gòu)圖
生活中的例子
橋接模式將抽象部分與它的實現(xiàn)分離,使它們能夠獨立地變化。一個普通的開關(guān)控制的電燈、電風扇等等,都是橋接的例子。開關(guān)的目的是將設(shè)備打開或關(guān)閉。實際的開關(guān)可以是簡單的雙刀拉鏈開關(guān),也可以是調(diào)光開關(guān)。
2 使用電子開關(guān)例子的橋接對象圖
橋接模式解說
在創(chuàng)建型模式里面,我曾經(jīng)提到過抽象與實現(xiàn),抽象不應(yīng)該依賴于具體實現(xiàn)細節(jié),實現(xiàn)細節(jié)應(yīng)該依賴于抽象。看下面這幅圖:
3 抽象不應(yīng)該依賴于實現(xiàn)細節(jié)
在這種情況下,如果抽象 B 穩(wěn)定,而實現(xiàn)細節(jié) b 變化,這時用創(chuàng)建型模式來解決沒有問題。但是如果抽象 B 也不穩(wěn)定,也是變化的,該如何解決?這就要用到 Bridge 模式了。
我們?nèi)匀挥萌罩居涗浌ぞ哌@個例子來說明 Bridge 模式。現(xiàn)在我們要開發(fā)一個通用的日志記錄工具,它支持數(shù)據(jù)庫記錄 DatabaseLog 和文本文件記錄 FileLog 兩種方式,同時它既可以運行在 .NET 平臺,也可以運行在 Java 平臺上。
根據(jù)我們的設(shè)計經(jīng)驗,應(yīng)該把不同的日志記錄方式分別作為單獨的對象來對待,并為日志記錄類抽象出一個基類 Log 出來,各種不同的日志記錄方式都繼承于該基類:
4 Log 類結(jié)構(gòu)圖
實現(xiàn)代碼如下:
public abstract class Log
{
public abstract void Write( string log);
}
public class DatabaseLog : Log
{
public override void Write( string log)
{
//......Log Database
}
}
public class TextFileLog : Log
{
public override void Write( string log)
{
//......Log Text File
}
}
另外考慮到不同平臺的日志記錄,對于操作數(shù)據(jù)庫、寫入文本文件所調(diào)用的方式可能是不一樣的,為此對于不同的日志記錄方式,我們需要提供各種不同平臺上的實現(xiàn),對上面的類做進一步的設(shè)計得到了下面的結(jié)構(gòu)圖:
5
實現(xiàn)代碼如下:
public class NDatabaseLog : DatabaseLog
{
public override void Write( string log)
{
//......(.NET 平臺)Log Database
}
}
public class JDatabaseLog : DatabaseLog
{
public override void Write( string log)
{
//......(Java 平臺)Log Database
}
}
public class NTextFileLog : TextFileLog
{
public override void Write( string log)
{
//......(.NET 平臺)Log Text File
}
}
public class JTextFileLog : TextFileLog
{
public override void Write( string log)
{
//......(Java 平臺)Log TextFile
}
}
現(xiàn)在的這種設(shè)計方案本身是沒有任何錯誤的,假如現(xiàn)在我們要引入一種新的 xml 文件的記錄方式,則上面的類結(jié)構(gòu)圖會變成:
6
如圖中藍色的部分所示,我們新增加了一個繼承于 Log 基類的子類,而沒有修改其它的子類,這樣也符合了開放 - 封閉原則。如果我們引入一種新的平臺,比如說我們現(xiàn)在開發(fā)的日志記錄工具還需要支持 Borland 平臺,此時該類結(jié)構(gòu)又變成了:
7
同樣我們沒有修改任何的東西,只是增加了兩個繼承于 DatabaseLog TextFileLog 的子類,這也符合了開放 - 封閉原則。
但是我們說這樣的設(shè)計是脆弱的,仔細分析就可以發(fā)現(xiàn),它還是存在很多問題,首先它在遵循開放 - 封閉原則的同時,違背了類的單一職責原則,即一個類只有一個引起它變化的原因,而這里引起 Log 類變化的原因卻有兩個,即日志記錄方式的變化和日志記錄平臺的變化;其次是重復代碼會很多,不同的日志記錄方式在不同的平臺上也會有一部分的代碼是相同的;再次是類的結(jié)構(gòu)過于復雜,繼承關(guān)系太多,難于維護,最后最致命的一點是擴展性太差。上面我們分析的變化只是沿著某一個方向,如果變化沿著日志記錄方式和不同的運行平臺兩個方向變化,我們會看到這個類的結(jié)構(gòu)會迅速的變龐大。
現(xiàn)在該是 Bridge 模式粉墨登場的時候了,我們需要解耦這兩個方向的變化,把它們之間的強耦合關(guān)系改成弱聯(lián)系。我們把日志記錄方式和不同平臺上的實現(xiàn)分別當作兩個獨立的部分來對待,對于日志記錄方式,類結(jié)構(gòu)圖仍然是:
8
現(xiàn)在我們引入另外一個抽象類 ImpLog ,它是日志記錄在不同平臺的實現(xiàn)的基類,結(jié)構(gòu)圖如下:
9
實現(xiàn)代碼如下:
public abstract class ImpLog
{
public abstract void Execute( string msg);
}
public class NImpLog : ImpLog
{
public override void Execute( string msg)
{
//...... .NET 平臺
}
}
public class JImpLog : ImpLog
{
public override void Execute( string msg)
{
//...... Java 平臺
}
}
這時對于日志記錄方式和不同的運行平臺這兩個類都可以獨立的變化了,我們要做的工作就是把這兩部分之間連接起來。那如何連接呢?在這里, Bridge 使用了對象組合的方式,類結(jié)構(gòu)圖如下:
10
實現(xiàn)代碼如下:
public abstract class Log
{
protected ImpLog implementor;
public ImpLog Implementor
{
set { implementor = value ; }
}
public virtual void Write( string log)
{
implementor.Execute(log);
}
}
public class DatabaseLog : Log
{
public override void Write( string log)
{
implementor.Execute(log);
}
}
public class TextFileLog : Log
{
public override void Write( string log)
{
implementor.Execute(log);
}
}
可以看到,通過對象組合的方式, Bridge 模式把兩個角色之間的繼承關(guān)系改為了耦合的關(guān)系,從而使這兩者可以從容自若的各自獨立的變化,這也是 Bridge 模式的本意。再來看一下客戶端如何去使用:
class App
{
public static void Main( string [] args)
{
//.NET 平臺下的Database Log
Log dblog = new DatabaseLog ();
dblog.Implementor = new NImpLog ();
dblog.Write();
//Java 平臺下的Text File Log
Log txtlog = new TextFileLog ();
txtlog.Implementor = new JImpLog ();
txtlog.Write();
}
}
可能有人會擔心說,這樣不就又增加了客戶程序與具體日志記錄方式之間的耦合性了嗎?其實這樣的擔心是沒有必要的,因為這種耦合性是由于對象的創(chuàng)建所帶來的,完全可以用創(chuàng)建型模式去解決,就不是這里我們所討論的內(nèi)容了。
最后我們再來考慮一個問題,為什么 Bridge 模式要使用對象組合的方式而不是用繼承呢?如果采用繼承的方式,則 Log 類, ImpLog 類都為接口,類結(jié)構(gòu)圖如下:
11
實現(xiàn)代碼如下:
public class NDatabaseLog : DatabaseLog , IImpLog
{
//......
}
public class JDatabaseLog : DatabaseLog , IImpLog
{
//......
}
public class NTextFileLog : TextFileLog , IImpLog
{
//......
}
public class JTextFileLog : TextFileLog , IImpLog
{
//......
}
如上圖中藍色的部分所示,它們既具有日志記錄方式的特性,也具有接口 IimpLog 的特性,它已經(jīng)違背了面向?qū)ο笤O(shè)計原則中類的單一職責原則,一個類應(yīng)當僅有一個引起它變化的原因。所以采用 Bridge 模式往往是比采用多繼承更好的方案。說到這里,大家應(yīng)該對 Bridge 模式有一些認識了吧?如果在開發(fā)中遇到有兩個方向上縱橫交錯的變化時,應(yīng)該能夠想到使用 Bridge 模式,當然了,有時候雖然有兩個方向上的變化,但是在某一個方向上的變化并不是很劇烈的時候,并不一定要使用 Bridge 模式。
效果及實現(xiàn)要點
1 Bridge 模式使用“對象間的組合關(guān)系”解耦了抽象和實現(xiàn)之間固有的綁定關(guān)系,使得抽象和實現(xiàn)可以沿著各自的維度來變化。
2 .所謂抽象和實現(xiàn)沿著各自維度的變化,即“子類化”它們,得到各個子類之后,便可以任意它們,從而獲得不同平臺上的不同型號。
3 Bridge 模式有時候類似于多繼承方案,但是多繼承方案往往違背了類的單一職責原則(即一個類只有一個變化的原因),復用性比較差。 Bridge 模式是比多繼承方案更好的解決方法。
4 Bridge 模式的應(yīng)用一般在“兩個非常強的變化維度”,有時候即使有兩個變化的維度,但是某個方向的變化維度并不劇烈——換言之兩個變化不會導致縱橫交錯的結(jié)果,并不一定要使用 Bridge 模式。
適用性
在以下的情況下應(yīng)當使用橋梁模式:
1 .如果一個系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的聯(lián)系。
2 .設(shè)計要求實現(xiàn)化角色的任何改變不應(yīng)當影響客戶端,或者說實現(xiàn)化角色的改變對客戶端是完全透明的。
3 .一個構(gòu)件有多于一個的抽象化角色和實現(xiàn)化角色,系統(tǒng)需要它們之間進行動態(tài)耦合。
4 .雖然在系統(tǒng)中使用繼承是沒有問題的,但是由于抽象化角色和具體化角色需要獨立變化,設(shè)計要求需要獨立管理這兩者。
總結(jié)
Bridge 模式是一個非常有用的模式,也非常復雜,它很好的符合了開放 - 封閉原則和優(yōu)先使用對象,而不是繼承這兩個面向?qū)ο笤瓌t。
參考資料
閻宏,《 Java 與模式》,電子工業(yè)出版社
James W. Cooper ,《 C# 設(shè)計模式》,電子工業(yè)出版社
Alan Shalloway James R. Trott ,《 Design Patterns Explained 》,中國電力出版社
MSDN WebCast C# 面向?qū)ο笤O(shè)計模式縱橫談 (8) Bridge 橋接模式 ( 結(jié)構(gòu)型模式 )

(第Ⅲ部分 結(jié)構(gòu)型模式篇) 第8章 橋接模式(Bridge Pattern)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产中文字幕免费 | 青青爽 | 99er热久久精品中文字幕 | 欧美a级成人淫片免费看 | 亚洲成人免费 | 国产真实强j视频在线观看 国产真实偷乱视频在线观看 | 四虎影院免费 | 国产成人亚洲综合网站不卡 | 亚洲99久久久久综合 | 夜色福利久久久久久777777 | 国产一区在线观看视频 | 香蕉综合网 | 欧美18videosex护士 | 日韩亚洲第一页 | 成人网视频在线观看免费 | 精品久久久久久乐 | 久久亚洲欧美成人精品 | 久久久高清免费视频 | 日本一区高清视频 | 手机看片自拍日韩日韩高清 | 一级毛片秋霞特色大片 | 久久久久久久久久免免费精品 | 久久精品一区二区影院 | 国产在线精品香蕉麻豆 | 亚洲精品宾馆在线精品酒店 | 欧美亚洲日本国产综合网 | 亚洲女精品一区二区三区 | 国产xxxx69免费大片 | 免费欧美在线视频 | 深夜色 | 国产图片区 | 九九热精品国产 | 婷婷 综合 | 国产人做人爱免费视频 | 久久久久久久久久综合情日本 | 91视频网| 久久综合狠狠综合久久综合88 | 中文字幕在亚洲第一在线 | 精品视频在线免费观看 | 日日摸夜夜摸狠狠摸日日碰夜夜做 | 99精品在线播放 |