標籤:不同的 根據 建立 nim protected 2.3 ted 五個 img
原文:C#設計模式之七橋接模式(Bridge Pattern)【結構型】
一、引言
今天我們要講【結構型】設計模式的第二個模式,該模式是【橋接模式】,也有叫【橋模式】的,英文名稱:Bridge Pattern。大家第一次看到這個名稱會想到什麼呢?我第一次看到這個模式根據名稱猜肯定是串連什麼東西的。因為橋在我們現實生活中經常是串連著A地和B地,再往後來發展,橋引申為一種紐帶,比如:絲綢之路是串連亞洲和歐洲的橋樑。有了橋,我們出行方便了,從一個地方到另一個地方在有橋的情況更方便了(此處不許抬杠,當然是需要橋的情況)。橋是針對橋的使用環境來說的,解決了跨越和銜接的問題。在設計模式中的【橋模式】也有類似的概念,是串連了兩個不同維度東西,而且這兩個維度又有強烈的變化,什麼叫強烈呢,經常變化,什麼是經常呢?哈哈,自己理解吧。
二、橋接模式的詳細介紹
2.1、動機(Motivate)
在很多遊戲情境中,會有這樣的情況:【裝備】本身會有的自己固有的邏輯,比如槍支,會有型號的問題,同時現在很多的遊戲又在不同的介質平台上運行和使用,這樣就使得遊戲的【裝備】具有了兩個變更維度——一個變更維度為“平台的變化”,另一個變更維度為“型號的變化”。如果我們要寫代碼實現這款遊戲,難道我們針對每種平台都實現一套獨立的【裝備】嗎?複用在哪裡?如何應對這種“多維度變化”?如何利用物件導向技術來使得【裝備】可以輕鬆地沿著“平台”和“型號”兩個方向變化,而不引入額外的複雜度?
2.2、意圖(Intent)
將抽象部分與實現部分分離,使它們都可以獨立地變化。 --《設計模式》Gof
橋模式不能只是認為是抽象和實現的分離,它其實並不僅限於此。其實兩個都是抽象的部分,更確切的理解,應該是將一個事物中多個維度變化分離。
2.3、結構圖(Structure)
2.4、模式的組成
橋接模式的結構包括Abstraction、RefinedAbstraction、Implementor、ConcreteImplementorA和ConcreteImplementorB五個部分,其中:
(1)、抽象化角色(Abstraction):抽象化給出的定義,並儲存一個對實現化對象(Implementor)的引用。
(2)、修正抽象化角色(Refined Abstraction):擴充抽象化角色,改變和修正父類對抽象化的定義。
(3)、實現化角色(Implementor):這個角色給出實現化角色的介面,但不給出具體的實現。必須指出的是,這個介面不一定和抽象化角色的介面定義相同,實際上,這兩個介面可以非常不一樣。實現化角色應當只給出底層操作,而抽象化角色應當只給出基於底層操作的更高一層的操作。
(4)、具體實現化角色(Concrete Implementor):這個角色給出實現化角色介面的具體實現。
在橋接模式中,兩個類Abstraction和Implementor分別定義了抽象與行為類型的介面,通過調用兩介面的子類實現抽象與行為的動態組合。
2.5 、橋接模式的具體代碼實現
今天我們就以資料庫為例來寫該模式的實現。每種資料庫都有自己的版本,但是每種資料庫在不同的平台上實現又是不一樣的。比如:微軟的SqlServer資料庫,該資料庫它有2000版本、2005版本、2006版本、2008版本,後面還會有更新的版本。並且這些版本都是運行在Windows作業系統下的,如果要提供Lunix作業系統下的SqlServer怎麼辦呢?如果又要提供IOS作業系統下的SqlServer資料庫該怎麼辦呢?這個情況就可以使用橋接模式,也就是Brige模式。我們就來看看具體的實現吧!
1 namespace 橋接模式的實現 2 { 3 /// <summary> 4 /// 該抽象類別就是抽象介面的定義,該類型就相當於是Abstraction類型 5 /// </summary> 6 public abstract class Database 7 { 8 //通過組合方式引用平台介面,此處就是橋樑,該類型相當於Implementor類型 9 protected PlatformImplementor _implementor;10 11 //通過構造器注入,初始化平台實現12 protected Database(PlatformImplementor implementor)13 {14 this._implementor = implementor;15 }16 17 //建立資料庫--該操作相當於Abstraction類型的Operation方法18 public abstract void Create();19 }20 21 /// <summary>22 /// 該抽象類別就是實現介面的定義,該類型就相當於是Implementor類型23 /// </summary>24 public abstract class PlatformImplementor25 {26 //該方法就相當於Implementor類型的OperationImpl方法27 public abstract void Process();28 }29 30 /// <summary>31 /// SqlServer2000版本的資料庫,相當於RefinedAbstraction類型32 /// </summary>33 public class SqlServer2000 : Database34 {35 //建構函式初始化36 public SqlServer2000(PlatformImplementor implementor) : base(implementor) { }37 38 public override void Create()39 {40 this._implementor.Process();41 }42 }43 44 /// <summary>45 /// SqlServer2005版本的資料庫,相當於RefinedAbstraction類型46 /// </summary>47 public class SqlServer2005 : Database48 {49 //建構函式初始化50 public SqlServer2005(PlatformImplementor implementor) : base(implementor) { }51 52 public override void Create()53 {54 this._implementor.Process();55 }56 }57 58 /// <summary>59 /// SqlServer2000版本的資料庫針對Unix作業系統具體的實現,相當於ConcreteImplementorA類型60 /// </summary>61 public class SqlServer2000UnixImplementor : PlatformImplementor62 {63 public override void Process()64 {65 Console.WriteLine("SqlServer2000針對Unix的具體實現");66 }67 }68 69 /// <summary>70 /// SqlServer2005版本的資料庫針對Unix作業系統的具體實現,相當於ConcreteImplementorB類型71 /// </summary>72 public sealed class SqlServer2005UnixImplementor : PlatformImplementor73 {74 public override void Process()75 {76 Console.WriteLine("SqlServer2005針對Unix的具體實現");77 }78 }79 80 public class Program81 {82 static void Main()83 {84 PlatformImplementor SqlServer2000UnixImp = new SqlServer2000UnixImplementor();85 //還可以針對不同平台進行擴充,也就是子類化,這個是獨立變化的86 87 Database SqlServer2000Unix = new SqlServer2000(SqlServer2000UnixImp);88 //資料庫版本也可以進行擴充和升級,也進行獨立的變化。89 90 //以上就是兩個維度變化。91 92 //就可以針對Unix執行操作了93 SqlServer2000Unix.Create();94 }95 }96 }
代碼都很簡單,也有詳細的備忘,就不多說了。
三、橋接模式的實現要點:
1.Bridge模式使用“對象間的組合關係”解耦了抽象和實現之間固有的綁定關係,使得抽象和實現可以沿著各自的維度來變化。
2.所謂抽象和實現沿著各自維度變化,即“子類化”它們,得到各個子類之後,便可以任意組合它們,從而獲得不同平台上的不同型號。
3.Bridge模式有時候類似於多繼承方案,但是多繼承方案往往違背了類的單一職責原則(即一個類只有一個變化的原因),複用性比較差。Bridge模式是比多繼承方案更好的解決方案。
4.Bridge模式的應用一般在“兩個非常強的變化維度”,有時候即使有兩個變更維度,但是某個方向的變化維度並不劇烈——換言之兩個變化不會導致縱橫交錯的結果,並不一定要使用Bridge模式。
3.1】、橋接模式的優點:
(1)、把抽象介面與其實現解耦。
(2)、抽象和實現可以獨立擴充,不會影響到對方。
(3)、實現細節對客戶透明,對用於隱藏了具體實現細節。
3.2】、橋接模式的缺點:
(1)、增加了系統的複雜度
3.3】、橋接模式的使用情境:
(1)、如果一個系統需要在構件的抽象化角色和具體化角色之間添加更多的靈活性,避免在兩個層次之間建立靜態聯絡。
(2)、設計要求實現化角色的任何改變不應當影響用戶端,或者實現化角色的改變對用戶端是完全透明的。
(3)、需要跨越多個平台的圖形和視窗系統上。
(4)、 一個類存在兩個獨立變更維度,且兩個維度都需要進行擴充。
四、.NET 中橋接模式的實現
學習中。。。,如果誰有好的代碼分享,也可以貼出來。
五、總結
今天的文章就寫到這裡了,現在小結一下。橋接模式它是串連用戶端代碼和具體實現代碼的一座橋樑,同時它也隔離了實現代碼的改變對客戶代碼的影響。在【意圖】中所說的抽象和實現,這兩個部分其實都是高度抽象的,前面“抽象”是指定義的針對用戶端的介面,用戶端其實使用的是Abstract類型或者是RefinedAbstract類型,這兩個類型只是介面,具體的實現委託給了Implementor類型了,Abstract類型子類化的擴充也演變成Implementor子類化的變化。我個人的理解,Abstract類型和其子類型在用戶端代碼和真正實現的代碼之間起到了橋樑的作用,隔離了Implementor實現代碼的變化,讓用戶端更穩定,所以【意圖】才說是講抽象部分和它的實現部分隔離。大家好好理解一下吧,剛開始有點繞。
C#設計模式之七橋接模式(Bridge Pattern)【結構型】