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

 #寫在前面

前面寫了那麼設計模式了,有沒有以爲有些模式之間很相似,甚至感受做用重疊了,模式並非徹底隔離和獨立的,有的模式內部其實用到了其餘模式的技術,可是又有本身的創新點,若是一味地認爲每一個模式都是獨一無二,與其餘模式徹底區別的,這是一種誤區html

 

 

#引入模式動機

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

    設想若是要繪製矩形、圓形、橢圓、正方形,咱們至少須要4個形狀類,可是若是繪製的圖形須要具備不一樣的顏色,如紅色、綠色、藍色等,此時至少有以下兩種設計方案:
        • 第一種設計方案是爲每一種形狀都提供一套各類顏色的版本。

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

 

對於有兩個變化維度(即兩個變化的緣由)的系統,採用方案二來進行設計系統中類的個數更少,且系統擴展更爲方便。設計方案二便是橋接模式的應用。橋接模式將繼承關係轉換爲關聯關係,從而下降了類與類之間的耦合,減小了代碼編寫量。編程

 

 

#模式定義

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

 通俗點講就是在不一樣的地方之間搭一座橋,讓他們鏈接起來,能夠相互通信和使用。
在模式中,就是爲被分離了的抽象部分和實現部分來搭橋。
橋接模式中的橋接是單向的,也就是隻能是抽象部分的對象去使用實現部分的對象,而不能反過來,也就是個單向橋。設計模式

 

 抽象化角色就像是一個水杯的手柄,而實現化角色和具體實現化角色就像是水杯的杯身。手柄控制杯身,這就是此模式別名「柄體」的來源。架構

 

 

#涉及角色

抽象化(Abstraction)角色:抽象化給出的定義,並保存一個對實現化對象的引用。
修正抽象化(Refined Abstraction)角色:擴展抽象化角色,改變和修正父類對抽象化的定義。
實現化(Implementor)角色:這個角色給出實現化角色的接口,但不給出具體的實現。必須指出的是,這個接口不必定和抽象化角色的接口定義相同,實際上,這兩個接口能夠很是不同。實現化角色應當只給出底層操做,而抽象化角色應當只給出基於底層操做的更高一層的操做。

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

 這些是從百度百科抄的.net

 

#橋接模式分析

橋樑模式的用意是"將抽象化(Abstraction)與實現化(Implementation)脫耦,使得兩者能夠獨立地變化"。這句話有三個關鍵詞,也就是抽象化、實現化和脫耦。設計

1)抽象化orm

存在於多個實體中的共同的概念性聯繫,就是抽象化。做爲一個過程,抽象化就是忽略一些信息,從而把不一樣的實體當作一樣的實體對待

2)實現化

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

3)脫耦

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

將兩個角色之間的繼承關係改成聚合關係,就是將它們之間的強關聯改換成爲弱關聯。所以,橋樑模式中的所謂脫耦,就是指在一個軟件系統的抽象化和實現化之間使用組合/聚合關係而不是繼承關係,從而使二者能夠相對獨立地變化。這就是橋樑模式的用意。

 這些是從百度百科抄的 

 

#橋接模式的優勢

    • 分離抽象接口及其實現部分。
    • 橋接模式有時相似於多繼承方案,可是多繼承方案違背了類的單一職責原則(即一個類只有一個變化的緣由),複用性比較差,並且多繼承結構中類的個數很是龐大,橋接模式是比多繼承方案更好的解決方法。
    • 橋接模式提升了系統的可擴充性,在兩個變化維度中任意擴展一個維度,都不須要修改原有系統。
    • 實現細節對客戶透明,能夠對用戶隱藏實現細節。

 

 

 #橋接模式的缺點

• 橋接模式的引入會增長系統的理解與設計難度,因爲聚合關聯關係創建在抽象層,要求開發者針對抽象進行設計與編程。

• 橋接模式要求正確識別出系統中兩個獨立變化的維度,所以其使用範圍具備必定的侷限性。

 

 

#橋接模式的應用場景

1)Java語言經過Java虛擬機實現了平臺的無關性

 

 

2)JDBC驅動器

橋樑模式在Java應用中一個很是典型的例子就是JDBC驅動器。JDBC爲全部的關係型數據庫提供一個通用的界面。一個應用系統動態的選擇一個合適的驅動器,而後經過驅動器向數據庫引擎發出指令。這個過程就是將抽象角色的行爲委派給實現角色的過程。

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

JDBC等級結構圖

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

JDBC這種架構,把抽象部分和具體實現部分分離開來,從而使得抽象部分和具體實現部分均可以獨立的擴展。對於應用程序而言,之遙選用不一樣的驅動,就可讓程序操做不一樣的數據庫,而無需更改應用程序,從而實如今不一樣的數據庫上移植;對於驅動程序而言,爲數據庫實現不一樣的驅動程序,並不會影響應用程序。




 

 

#適合使用橋接模式的情景

    • 若是一個系統須要在構件的抽象化角色和具體化角色之間增長更多的靈活性,避免在兩個層次之間創建靜態的繼承聯繫,經過橋接模式可使它們在抽象層創建一個關聯關係。
    • 抽象化角色和實現化角色能夠以繼承的方式獨立擴展而互不影響,在程序運行時能夠動態將一個抽象化子類的對象和一個實現化子類的對象進行組合,即系統須要對抽象化角色和實現化角色進行動態耦合。
    • 一個類存在兩個獨立變化的維度,且這兩個維度都須要進行擴展。
    • 雖然在系統中使用繼承是沒有問題的,可是因爲抽象化角色和具體化角色須要獨立變化,設計要求須要獨立管理這二者。
    • 對於那些不但願使用繼承或由於多層次繼承致使系統類的個數急劇增長的系統,橋接模式尤其適用。
 
 

#類結構

# 接口實現類
class Implementor:
    def Operation(self):
        raise NotImplementedError

class ConcreteImplementorA(Implementor):
    def Operation(self):
        print("實現 A的方法")

class ConcreteImplementorB(Implementor):
    def Operation(self):
        print("實現 B的方法")
# 抽象類
class Abstraction():
    def __init__(self,implementor):
        self.implementor = implementor
    def Operation(self):
        raise NotImplementedError

class RefineAbstraction(Abstraction):
    def Operation(self):
        self.implementor.Operation()

if __name__ == "__main__":
    a = ConcreteImplementorA()
    b = ConcreteImplementorB()
    aa = RefineAbstraction(a)
    ab = RefineAbstraction(b)
    aa.Operation()
    ab.Operation()


 

 
#舉個例子
 
#抽象類:人
class people:
    def set_skill(self,skill):
        self.skill=skill
    def perform_skill(self):
        pass

#具體抽象類:花匠
class hua_j(people):
    def perform_skill(self):
        print('我是花匠')
        self.skill.perform_skill()
#具體抽象類:木匠
class mu_j(people):
    def perform_skill(self):
        print('我是木匠')
        self.skill.perform_skill()
#具體抽象類:鐵匠
class tie_j(people):
    def perform_skill(self):
        print('我是鐵匠')
        self.skill.perform_skill()
    

#功能類,也是實現類
class  skill:
    def perform_skill(self):
        pass
    
#具體功能類,也是具體實現類 種花
class  skill_hua(skill):
    def perform_skill(self):
        print('我會種花')
    
#具體功能類,也是具體實現類 作木桌子
class  skill_mu:
    def perform_skill(self):
        print('我會作木桌子')

#具體功能類,也是具體實現類 作鐵桌子
class  skill_tie:
    def perform_skill(self):
        print('我會作鐵桌子')

#具體功能類,也是具體實現類 作老師
class  skill_teacher:
    def perform_skill(self):
        print('我會作老師,能夠教學生')
#具體功能類,也是具體實現類 作傢俱
class  skill_jj:
    def perform_skill(self):
        print('我會作傢俱')

def main():
    h=hua_j() #花匠
    m=mu_j() #木匠
    t=tie_j() #鐵匠

    sh=skill_hua()# 本事:會種花
    sm=skill_mu() #本事:會作木頭桌子
    st=skill_tie() #本事:會作鐵桌子
    s_t=skill_teacher() #本事:會教學生
    s_jj=skill_jj() #本事:會作傢俱

    h.set_skill(sh) #給花匠set種花的本事
    h.perform_skill() #花匠 種花
    h.set_skill(s_t) #給花匠set作老師的本事
    h.perform_skill() #花匠教學生

    print('=============')
    m.set_skill(sm) #給木匠set 作木桌子的本事
    m.perform_skill() #木匠 作木桌子
    m.set_skill(s_t) #給木匠set作老師的本事
    m.perform_skill() #木匠教學生
    m.set_skill(s_jj) #給木匠set作傢俱的本事
    m.perform_skill() #木匠作傢俱

    print('=============')
    t.set_skill(st) #給木匠set 作木桌子的本事
    t.perform_skill() #木匠 作木桌子
    t.set_skill(s_t) #給木匠set作老師的本事
    t.perform_skill() #木匠教學生
    t.set_skill(s_jj) #給木匠set作傢俱的本事
    t.perform_skill() #木匠作傢俱


if __name__ == '__main__':
    main()

 

 
 

 

參考

https://www.cnblogs.com/WindSun/p/10260547.html

https://baike.baidu.com/item/%E6%A1%A5%E6%8E%A5%E6%A8%A1%E5%BC%8F/5293399?fr=aladdin

https://www.cnblogs.com/zyrblog/p/9233189.html

https://blog.csdn.net/sunyqcn/article/details/85113751

https://www.jianshu.com/p/775cb53a4da2

https://www.cnblogs.com/qq_841161825/articles/10142201.html

 https://blog.csdn.net/weixin_41431904/article/details/80783839

相關文章
相關標籤/搜索