摘要:橋接模式和裝飾模式的區(qū)別設(shè)計模式裝飾模式橋接模式和裝飾模式都是通過將繼承關(guān)系轉(zhuǎn)換為關(guān)聯(lián)關(guān)系從而減少系統(tǒng)中類的數(shù)量,降低系統(tǒng)的耦合性。裝飾器模式支持多層裝飾,通過不同的組合可以實現(xiàn)不同的行為。
產(chǎn)生橋接模式的動機(jī):
假設(shè)這樣一種情況:
我們有大中小型號的毛筆,有紅藍(lán)黑三種顏料。如果需要不同顏色,不同型號的毛筆有如下兩種設(shè)計方法:
為每一種型號的毛筆都提供三種顏料的版本。
將毛筆和顏料分開,使用的時候自由組合。
針對第一種我們當(dāng)下就需要紅色顏料大號毛筆、藍(lán)色顏料大號毛筆等九中型號,在之后的擴(kuò)展中,每增加一個型號的毛筆就需要為其增加所有顏料的版本, 而每增加一種顏料也需要為所有的筆增添新的顏料類型。隨著筆的類型和顏料種類的不斷增長,其類數(shù)量的增加速度為O(n!) 我們需要維護(hù)龐大的種類集合。
而第二種我們將筆和顏料分開,就比如說準(zhǔn)備大中小三種型號的毛筆,以及紅藍(lán)黑三種顏料,用的時候就拿筆區(qū)蘸一下顏料就可以,這樣筆和顏料解耦,他們可以分開增加。其類的增加速度為O(n) 我們可以看出 O(n!)的增長速度遠(yuǎn)大于O(n)。
第一種方法在系統(tǒng)設(shè)計上我們采用的就是繼承的方式。實現(xiàn)方式上有兩種,一種就像我上面提到的只有一個抽象類,然后所有子類都是由這個抽象類里面派生出來了,還有一種代碼編寫方式就是提供毛筆抽象類和顏料抽象類 以及他們的派生子類,然后子類使用多繼承分別繼承他們,這種編寫方式又一個問題就是在不支持多繼承的語言中無法實現(xiàn)(例子請看我的 文章中的那一部分。)
第二種方法是采用組合關(guān)系的設(shè)計,其設(shè)計中也是將顏料和筆這兩個變化分開,及分別由筆的抽象類派生出各種各樣的筆和由顏料抽象類派生出的各種各樣的顏料。但是將他們之間連接在一起的是關(guān)聯(lián)關(guān)系方式(不懂的可以區(qū)我的這一篇文章看一下)。在結(jié)構(gòu)型設(shè)計模式中大量使用這種關(guān)聯(lián)關(guān)系來代替繼承關(guān)系以實現(xiàn)解耦,為什么關(guān)聯(lián)關(guān)系可以解耦呢?我認(rèn)為主要有以下幾點:
繼承關(guān)系中,父類的修改會傳播到子類中,容易造成子類的不穩(wěn)定。
繼承關(guān)系在代碼編寫階段已經(jīng)固定,但是使用關(guān)聯(lián)關(guān)系,我們可以將他們之間的關(guān)系確定推遲到程序運行時,更加方便用戶控制。比如使用配置文件來確定關(guān)聯(lián)關(guān)系中的兩個類的類型。
使用關(guān)聯(lián)關(guān)系也可以減少代碼的編寫量,尤其是在變化的種類很多以及后期增加種類的時候。
使用關(guān)聯(lián)關(guān)系在后期增加變化種類,不需要更改已經(jīng)存在的類。滿足開閉原則
使用關(guān)聯(lián)關(guān)系也將功能分割,符合單一職責(zé)原則
橋接模式的定義:橋接模式(Bridge Pattern):將抽象部分與它的實現(xiàn)部分分離,使它們都可以獨立地變化。它是一種對象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式。
實現(xiàn) 使用繼承方式的實現(xiàn) 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()使用橋接模式重構(gòu)后 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()代碼分析
在上面的繼承方式的實現(xiàn)中我們采用的是單繼承,在我的python設(shè)計模式-裝飾模式采用繼承方式就是多繼承。橋接模式有時類似多繼承方法。不過橋接模式產(chǎn)生了很多不同的小對象而多繼承方案產(chǎn)生了很多不同的小類。但是多繼承方案違背了類的單一職責(zé)原則(即一個類只應(yīng)該有一個變化的原因),其次多繼承關(guān)系的確定在編碼階段就已經(jīng)確定,無法靈活的擴(kuò)展,還有就是很多語言是不支持多繼承的。
橋接模式的優(yōu)缺點 優(yōu)點分離了抽象接口與實現(xiàn)部分
提高系統(tǒng)可擴(kuò)充性,在兩個緯度中任意擴(kuò)展,都不需對原系統(tǒng)進(jìn)行修改。
缺點橋接模式的引入會增加系統(tǒng)的理解與設(shè)計難度,由于聚合關(guān)聯(lián)關(guān)系建立在抽象層,要求開發(fā)者針對抽象進(jìn)行設(shè)計與編程。 - 橋接模式要求正確識別出系統(tǒng)中兩個獨立變化的維度,因此其使用范圍具有一定的局限性。
適用環(huán)境如果一個系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的繼承聯(lián)系,通過橋接模式可以使它們在抽象層建立一個關(guān)聯(lián)關(guān)系。
抽象化角色和實現(xiàn)化角色可以以繼承的方式獨立擴(kuò)展而互不影響,在程序運行時可以動態(tài)將一個抽象化子類的對象和一個實現(xiàn)化子類的對象進(jìn)行組合,即系統(tǒng)需要對抽象化角色和實現(xiàn)化角色進(jìn)行動態(tài)耦合。
一個類存在兩個獨立變化的維度,且這兩個維度都需要進(jìn)行擴(kuò)展。
雖然在系統(tǒng)中使用繼承是沒有問題的,但是由于抽象化角色和具體化角色需要獨立變化,設(shè)計要求需要獨立管理這兩者。
對于那些不希望使用繼承或因為多層次繼承導(dǎo)致系統(tǒng)類的個數(shù)急劇增加的系統(tǒng),橋接模式尤為適用。
橋接模式和裝飾模式的區(qū)別python設(shè)計模式-裝飾模式
橋接模式和裝飾模式都是通過將繼承關(guān)系轉(zhuǎn)換為關(guān)聯(lián)關(guān)系從而減少系統(tǒng)中類的數(shù)量,降低系統(tǒng)的耦合性。
橋接模式是解決一個系統(tǒng)有多個變化維度的一種設(shè)計模式。其難點是如何將其中的抽象化與實現(xiàn)化分離(抽象化是指將一組復(fù)雜物體的一個或幾個特征抽取出來形成共用部分,在面向?qū)ο蟮某绦蛟O(shè)計中就是將對象共同的性質(zhì)抽取出去而形成類的過程。實現(xiàn)化是指給出抽象化中的具體實現(xiàn),他是對抽象化的建進(jìn)一步具體化)。使用關(guān)聯(lián)關(guān)系在運行時設(shè)置不同的具體類來讓同一個抽象對象表現(xiàn)出不同的行為。在整個過程中抽象化的類其實是不穩(wěn)定的,不穩(wěn)定指我們通過傳入不同的實現(xiàn)類改變了抽象類本身的運行結(jié)果。
裝飾器模式是解決如何給一個類動態(tài)增加職責(zé)的一種設(shè)計模式。裝飾器模式通過將一個類中需要動態(tài)執(zhí)行的方法抽取出來形成裝飾類,通過關(guān)聯(lián)關(guān)系來將職責(zé)的添加推遲到了程序運行時。如果程序支持反射還可以通過配置文件來靈活更改對象的功能。裝飾器模式支持多層裝飾,通過不同的組合可以實現(xiàn)不同的行為。在整個過程中被裝飾對象是穩(wěn)定的。因為裝飾模式是在被裝飾對象的前后增加功能,而不是改變被裝飾對象本身的功能。具體的裝飾類和被裝飾類可以獨立變化,用戶根據(jù)需要動態(tài)的增加裝飾類和被裝飾類,并在調(diào)用的時候進(jìn)行組合,無需更改之前的代碼,符合開閉原則。
從實現(xiàn)上看橋接模式中抽象類只包含一個實現(xiàn)類的引用,實現(xiàn)對實現(xiàn)類的調(diào)用。而裝飾模式中抽象裝飾類繼承構(gòu)件抽類類,并且還包含一個對抽象構(gòu)建的引用。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/44497.html
摘要:本文只是尋找設(shè)計模式在中的應(yīng)用。來補全這一塊工廠模式中的應(yīng)用包線程池解釋和代碼線程池中有線程創(chuàng)建工廠。狀態(tài)模式中的應(yīng)用解釋和代碼根據(jù)一個指針的狀態(tài)而改變自己的行為適配器模式中的應(yīng)用解釋和代碼將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口。 前言 最近重學(xué)設(shè)計模式,而且還有很多源碼要看。所以就想一舉兩得。從源碼中尋找設(shè)計模式。順便還可以看看源碼。。。本文只是尋找設(shè)計模式在java中的應(yīng)用。優(yōu)...
摘要:作為一個前端新人,學(xué)習(xí)了設(shè)計模式以后,希望能從源頭上,用淺顯易懂的語言來解釋它。創(chuàng)建型設(shè)計模式創(chuàng)建型設(shè)計模式故名思意,這些模式都是用來創(chuàng)建實例對象的。這就是簡單工廠模式。這就是工廠方法模式。 作為一個前端新人,學(xué)習(xí)了設(shè)計模式以后,希望能從源頭上,用淺顯易懂的語言來解釋它。當(dāng)然不一定是正確的,只是我個人對設(shè)計模式的一點淺顯理解。 創(chuàng)建型設(shè)計模式 創(chuàng)建型設(shè)計模式:故名思意,這些模式都是用來...
摘要:這種模式我們稱之為裝飾器模式。因為裝飾器模式是在給對象增加責(zé)任。以下情況適合使用裝飾器模式在不影響其他對象的情況下,以動態(tài)透明的方式給單個對象添加職責(zé)。 前言 本篇的裝飾器模式不是講解的python中的語法糖 @ 這個裝飾器。而是講解設(shè)計模式中的裝飾器模式。網(wǎng)上很多的實現(xiàn)都是基于java和c++的。本文則使用python來實現(xiàn),其中有些實現(xiàn)可能在python并不需要那樣來寫的,但是思路...
摘要:橋接模式屬于結(jié)構(gòu)型模式的一種,用于把抽象化與實現(xiàn)化解耦,使得二者可以獨立變化,它通過提供抽象化和實現(xiàn)化之間的橋接結(jié)構(gòu),來實現(xiàn)二者的解耦。相關(guān)模式裝飾模式與橋接模式在一定程度上都是為了減少子類的數(shù)目,避免出現(xiàn)復(fù)雜的繼承關(guān)系。 橋接模式(Brideg Pattern)屬于結(jié)構(gòu)型模式的一種,用于把抽象化與實現(xiàn)化解耦,使得二者可以獨立變化,它通過提供抽象化和實現(xiàn)化之間的橋接結(jié)構(gòu),來實現(xiàn)二者的解...
閱讀 2598·2023-04-26 03:00
閱讀 1410·2021-10-12 10:12
閱讀 4208·2021-09-22 15:33
閱讀 2933·2021-09-22 15:06
閱讀 1545·2019-08-30 15:44
閱讀 2160·2019-08-30 13:59
閱讀 544·2019-08-30 11:24
閱讀 2433·2019-08-29 17:07