天天看點

python 設計模式之橋接模式 Bridge Pattern

前面寫了那麼設計模式了,有沒有覺得有些模式之間很類似,甚至感覺作用重疊了,模式并不是完全隔離和獨立的,有的模式内部其實用到了其他模式的技術,但是又有自己的創新點,如果一味地認為每個模式都是獨一無二,與其他模式完全差別的,這是一種誤區

這個例子清晰而直白的說明了為啥要用橋接模式,我就拿過來用了,連結在參考裡

    設想如果要繪制矩形、圓形、橢圓、正方形,我們至少需要4個形狀類,但是如果繪制的圖形需要具有不同的顔色,如紅色、綠色、藍色等,此時至少有如下兩種設計方案:

        • 第一種設計方案是為每一種形狀都提供一套各種顔色的版本。

python 設計模式之橋接模式 Bridge Pattern

        • 第二種設計方案是根據實際需要對形狀和顔色進行組合。

python 設計模式之橋接模式 Bridge Pattern

對于有兩個變化次元(即兩個變化的原因)的系統,采用方案二來進行設計系統中類的個數更少,且系統擴充更為友善。設計方案二即是橋接模式的應用。橋接模式将繼承關系轉換為關聯關系,進而降低了類與類之間的耦合,減少了代碼編寫量。

橋接模式(Bridge Pattern):将抽象部分與它的實作部分分離,使它們都可以獨立地變化。它是一種對象結構型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式。

 通俗點講就是在不同的地方之間搭一座橋,讓他們連接配接起來,可以互相通訊和使用。

在模式中,就是為被分離了的抽象部分和實作部分來搭橋。

橋接模式中的橋接是單向的,也就是隻能是抽象部分的對象去使用實作部分的對象,而不能反過來,也就是個單向橋。

 抽象化角色就像是一個水杯的搖桿,而實作化角色和具體實作化角色就像是水杯的杯身。搖桿控制杯身,這就是此模式别名“柄體”的來源。

抽象化(Abstraction)角色:抽象化給出的定義,并儲存一個對實作化對象的引用。

修正抽象化(Refined Abstraction)角色:擴充抽象化角色,改變和修正父類對抽象化的定義。

實作化(Implementor)角色:這個角色給出實作化角色的接口,但不給出具體的實作。必須指出的是,這個接口不一定和抽象化角色的接口定義相同,實際上,這兩個接口可以非常不一樣。實作化角色應當隻給出底層操作,而抽象化角色應當隻給出基于底層操作的更高一層的操作。

具體實作化(Concrete Implementor)角色:這個角色給出實作化角色接口的具體實作

 這些是從百度百科抄的

橋梁模式的用意是"将抽象化(Abstraction)與實作化(​​Implementation​​)​​脫耦​​,使得二者可以獨立地變化"。這句話有三個關鍵詞,也就是抽象化、實作化和脫耦。

1)抽象化

存在于多個實體中的共同的概念性聯系,就是抽象化。作為一個過程,抽象化就是忽略一些資訊,進而把不同的實體當做同樣的實體對待

2)實作化

抽象化給出的具體實作,就是實作化

3)脫耦

所謂耦合,就是兩個實體的行為的某種強關聯。而将它們的強關聯去掉,就是耦合的解脫,或稱脫耦。在這裡,脫耦是指将抽象化和實作化之間的耦合解脫開,或者說是将它們之間的強關聯改換成弱關聯。

将兩個角色之間的繼承關系改為聚合關系,就是将它們之間的強關聯改換成為弱關聯。是以,橋梁模式中的所謂脫耦,就是指在一個軟體系統的抽象化和實作化之間使用組合/聚合關系而不是繼承關系,進而使兩者可以相對獨立地變化。這就是橋梁模式的用意。

 這些是從百度百科抄的 

    • 分離抽象接口及其實作部分。

    • 橋接模式有時類似于多繼承方案,但是多繼承方案違背了類的單一職責原則(即一個類隻有一個變化的原因),複用性比較差,而且多繼承結構中類的個數非常龐大,橋接模式是比多繼承方案更好的解決方法。

    • 橋接模式提高了系統的可擴充性,在兩個變化次元中任意擴充一個次元,都不需要修改原有系統。

    • 實作細節對客戶透明,可以對使用者隐藏實作細節。

• 橋接模式的引入會增加系統的了解與設計難度,由于聚合關聯關系建立在抽象層,要求開發者針對抽象進行設計與程式設計。

• 橋接模式要求正确識别出系統中兩個獨立變化的次元,是以其使用範圍具有一定的局限性。

1)Java語言通過Java虛拟機實作了平台的無關性

python 設計模式之橋接模式 Bridge Pattern

2)JDBC驅動器

橋梁模式在Java應用中一個非常典型的例子就是JDBC驅動器。JDBC為所有的關系型資料庫提供一個通用的界面。一個應用系統動态的選擇一個合适的驅動器,然後通過驅動器向資料庫引擎發出指令。這個過程就是将抽象角色的行為委派給實作角色的過程。

抽象角色可以針對任何資料庫引擎發出查詢指令,因為抽象角色并不直接�與資料庫引擎打交道,JDBC驅動器負責這個底層的工作。由于JDBC驅動器的存在,應用系統可以不依賴于資料庫引擎的細節而獨立的演化;同時資料庫引擎也可以獨立�于應用系統的細節而獨立的演化。兩個獨立的等級結構圖如下圖所示,左邊是JDBC API的等級結構,右邊是JDBC驅動器的等級結構,應用程式是建立在JDBC API的基礎之上的。

python 設計模式之橋接模式 Bridge Pattern

JDBC等級結構圖

應用系統作為一個等級結構,與JDBC驅動器這個等級結構是相對獨立的,它們之間沒有靜态的強關聯。應用系統通過委派與JDBC驅動器互相作用,這是一個橋梁模式的例子。

JDBC這種架構,把抽象部分和具體實作部分分離開來,進而使得抽象部分和具體實作部分都可以獨立的擴充。對于應用程式而言,之遙選用不同的驅動,就可以讓程式操作不同的資料庫,而無需更改應用程式,進而實作在不同的資料庫上移植;對于驅動程式而言,為資料庫實作不同的驅動程式,并不會影響應用程式。

    • 如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜态的繼承聯系,通過橋接模式可以使它們在抽象層建立一個關聯關系。

    • 抽象化角色和實作化角色可以以繼承的方式獨立擴充而互不影響,在程式運作時可以動态将一個抽象化子類的對象和一個實作化子類的對象進行組合,即系統需要對抽象化角色和實作化角色進行動态耦合。

    • 一個類存在兩個獨立變化的次元,且這兩個次元都需要進行擴充。

    • 雖然在系統中使用繼承是沒有問題的,但是由于抽象化角色和具體化角色需要獨立變化,設計要求需要獨立管理這兩者。

    • 對于那些不希望使用繼承或因為多層次繼承導緻系統類的個數急劇增加的系統,橋接模式尤為适用。

#舉個例子

python 設計模式之橋接模式 Bridge Pattern