python設計模式-橋接模式&比較橋接模式和裝飾模式的不一樣

產生橋接模式的動機:

假設這樣一種狀況:
咱們有大中小型號的毛筆,有紅藍黑三種顏料。若是須要不一樣顏色,不一樣型號的毛筆有以下兩種設計方法:python

  1. 爲每一種型號的毛筆都提供三種顏料的版本。
  2. 將毛筆和顏料分開,使用的時候自由組合。

針對第一種咱們當下就須要紅色顏料大號毛筆、藍色顏料大號毛筆等九中型號,在以後的擴展中,每增長一個型號的毛筆就須要爲其增長全部顏料的版本, 而每增長一種顏料也須要爲全部的筆增添新的顏料類型。隨着筆的類型和顏料種類的不斷增加,其類數量的增長速度爲O(n!) 咱們須要維護龐大的種類集合。
而第二種咱們將筆和顏料分開,就好比說準備大中小三種型號的毛筆,以及紅藍黑三種顏料,用的時候就拿筆區蘸一下顏料就能夠,這樣筆和顏料解耦,他們能夠分開增長。其類的增長速度爲O(n) 咱們能夠看出 O(n!)的增加速度遠大於O(n)。編程

第一種方法在系統設計上咱們採用的就是繼承的方式。實現方式上有兩種,一種就像我上面提到的只有一個抽象類,而後全部子類都是由這個抽象類裏面派生出來了,還有一種代碼編寫方式就是提供毛筆抽象類和顏料抽象類 以及他們的派生子類,而後子類使用多繼承分別繼承他們,這種編寫方式又一個問題就是在不支持多繼承的語言中沒法實現(例子請看個人 文章中的那一部分。)segmentfault

第二種方法是採用組合關係的設計,其設計中也是將顏料和筆這兩個變化分開,及分別由筆的抽象類派生出各類各樣的筆和由顏料抽象類派生出的各類各樣的顏料。可是將他們之間鏈接在一塊兒的是關聯關係方式(不懂的能夠區個人這一篇文章看一下)。在結構型設計模式中大量使用這種關聯關係來代替繼承關係以實現解耦,爲何關聯關係能夠解耦呢?我認爲主要有如下幾點:設計模式

  1. 繼承關係中,父類的修改會傳播到子類中,容易形成子類的不穩定。
  2. 繼承關係在代碼編寫階段已經固定,可是使用關聯關係,咱們能夠將他們之間的關係肯定推遲到程序運行時,更加方便用戶控制。好比使用配置文件來肯定關聯關係中的兩個類的類型。
  3. 使用關聯關係也能夠減小代碼的編寫量,尤爲是在變化的種類不少以及後期增長種類的時候。
  4. 使用關聯關係在後期增長變化種類,不須要更改已經存在的類。知足開閉原則
  5. 使用關聯關係也將功能分割,符合單一職責原則

橋接模式的定義:

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

實現

使用繼承方式的實現

UML類圖

圖片描述

python 代碼

class BrushAbstraction(object):
    def __init__(self, size, color):
        self.paint = None
        self.__size = size
        self.__color = color

    def draw(self):
        print('Use {} {} brush draw'.format(self.__color, self.__size))


class BigBrushAbstration(BrushAbstraction):
    def __init__(self, color):
        super(BigBrushAbstration, self).__init__('Big', color)


class MiddleBrushAbstration(BrushAbstraction):
    def __init__(self, color):
        super(MiddleBrushAbstration, self).__init__('Middle', color)


class SmallBrushAbstration(BrushAbstraction):
    def __init__(self, color):
        super(SmallBrushAbstration, self).__init__('Small', color)


class RedBigBrushAbstration(BigBrushAbstration):
    def __init__(self):
        super(RedBigBrushAbstration, self).__init__('Red')


class BlueBigBrushAbstration(BigBrushAbstration):
    def __init__(self):
        super(BlueBigBrushAbstration, self).__init__('Blue')


class BlackBigBrushAbstration(BigBrushAbstration):
    def __init__(self):
        super(BlackBigBrushAbstration, self).__init__('Black')


class RedMiddleBrushAbstration(MiddleBrushAbstration):
    def __init__(self):
        super(RedMiddleBrushAbstration, self).__init__('Red')


class BlueMiddleBrushAbstration(MiddleBrushAbstration):
    def __init__(self):
        super(BlueMiddleBrushAbstration, self).__init__('Blue')


class BlackMiddleBrushAbstration(MiddleBrushAbstration):
    def __init__(self):
        super(BlackMiddleBrushAbstration, self).__init__('Black')


class RedSmallBrushAbstration(SmallBrushAbstration):
    def __init__(self):
        super(RedSmallBrushAbstration, self).__init__('Red')


class BlueSmallBrushAbstration(SmallBrushAbstration):
    def __init__(self):
        super(BlueSmallBrushAbstration, self).__init__('Blue')


class BlackSmallBrushAbstration(SmallBrushAbstration):
    def __init__(self):
        super(BlackSmallBrushAbstration, self).__init__('Black')


if __name__ == '__main__':
    blue_big_brush = BlueBigBrushAbstration()
    blue_big_brush.draw()

    black_big_brush = BlackBigBrushAbstration()
    black_big_brush.draw()

使用橋接模式重構後

UML類圖

圖片描述

代碼

class BrushAbstraction(object):
    def __init__(self, size):
        self.paint = None
        self.__size = size

    def dip_paint(self, paint):
        self.paint = paint

    def draw(self):
        print('Use {} {} brush draw'.format(self.paint.color(), self.__size))


class BigBrushAbstration(BrushAbstraction):
    def __init__(self):
        super(BigBrushAbstration, self).__init__('Big')


class MiddleBrushAbstration(BrushAbstraction):
    def __init__(self):
        super(MiddleBrushAbstration, self).__init__('Middle')


class SmallBrushAbstration(BrushAbstraction):
    def __init__(self):
        super(SmallBrushAbstration, self).__init__('Small')


class PaintImplementer(object):
    def __init__(self, color):
        self.__color = color

    def color(self):
        return self.__color


class RedPaintImplementer(PaintImplementer):
    def __init__(self):
        super(RedPaintImplementer, self).__init__('Red')


class BluePaintImplementer(PaintImplementer):
    def __init__(self):
        super(BluePaintImplementer, self).__init__('Blue')


class BlackPaintImplementer(PaintImplementer):
    def __init__(self):
        super(BlackPaintImplementer, self).__init__('Black')


if __name__ == '__main__':
    big_bursh = BigBrushAbstration()
    big_bursh.dip_paint(BluePaintImplementer())
    big_bursh.draw()

    big_bursh.dip_paint(BlackPaintImplementer())
    big_bursh.draw()

代碼分析

在上面的繼承方式的實現中咱們採用的是單繼承,在個人python設計模式-裝飾模式採用繼承方式就是多繼承。橋接模式有時相似多繼承方法。不過橋接模式產生了不少不一樣的小對象而多繼承方案產生了不少不一樣的小類。可是多繼承方案違背了類的單一職責原則(即一個類只應該有一個變化的緣由),其次多繼承關係的肯定在編碼階段就已經肯定,沒法靈活的擴展,還有就是不少語言是不支持多繼承的。spa

橋接模式的優缺點

優勢

  1. 分離了抽象接口與實現部分
  2. 提升系統可擴充性,在兩個緯度中任意擴展,都不需對原系統進行修改。

缺點

橋接模式的引入會增長系統的理解與設計難度,因爲聚合關聯關係創建在抽象層,要求開發者針對抽象進行設計與編程。 - 橋接模式要求正確識別出系統中兩個獨立變化的維度,所以其使用範圍具備必定的侷限性。設計

適用環境

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

橋接模式和裝飾模式的區別

python設計模式-裝飾模式code

  1. 橋接模式和裝飾模式都是經過將繼承關係轉換爲關聯關係從而減小系統中類的數量,下降系統的耦合性。
  2. 橋接模式是解決一個系統有多個變化維度的一種設計模式。其難點是如何將其中的抽象化與實現化分離(抽象化是指將一組複雜物體的一個或幾個特徵抽取出來造成共用部分,在面向對象的程序設計中就是將對象共同的性質抽取出去而造成類的過程。實現化是指給出抽象化中的具體實現,他是對抽象化的建進一步具體化)。使用關聯關係在運行時設置不一樣的具體類來讓同一個抽象對象表現出不一樣的行爲。在整個過程當中抽象化的類實際上是不穩定的,不穩定指咱們經過傳入不一樣的實現類改變了抽象類自己的運行結果。
  3. 裝飾器模式是解決如何給一個類動態增長職責的一種設計模式。裝飾器模式經過將一個類中須要動態執行的方法抽取出來造成裝飾類,經過關聯關係來將職責的添加推遲到了程序運行時。若是程序支持反射還能夠經過配置文件來靈活更改對象的功能。裝飾器模式支持多層裝飾,經過不一樣的組合能夠實現不一樣的行爲。在整個過程當中被裝飾對象是穩定的。由於裝飾模式是在被裝飾對象的先後增長功能,而不是改變被裝飾對象自己的功能。具體的裝飾類和被裝飾類能夠獨立變化,用戶根據須要動態的增長裝飾類和被裝飾類,並在調用的時候進行組合,無需更改以前的代碼,符合開閉原則。
  4. 從實現上看橋接模式中抽象類只包含一個實現類的引用,實現對實現類的調用。而裝飾模式中抽象裝飾類繼承構件抽類類,而且還包含一個對抽象構建的引用。
相關文章
相關標籤/搜索