Bridge橋接模式(結構型模式)
現有一個需求,一個遊戲系統需要構建不同風格的房屋,暫不考慮其他設計模式,需要能實現在PC端、移動端....等等多個平臺的構建.最簡單的實現方式如下:
/// <summary> /// 房屋抽象 /// </summary> public abstract class House { /// <summary> /// 不同平臺的初始化方法 /// </summary> public abstractvoid PlatformInit(); /// <summary> /// 繪製窗戶 /// </summary> public abstract void DrowWindow(); /// <summary> /// 繪製門 /// </summary> public abstract void DrowDoor(); } /// <summary>/// PC版的現代化房屋構建過程 /// </summary> public class PCModernHouse : House { public override void DrowDoor() { } public override void DrowWindow() { } publicoverride void PlatformInit() { //這裡初始化構建PC版的現代化房屋所需要的PC平臺的相關資訊 } } /// <summary> /// 移動端的現代化房屋構建過程 /// </summary> public class MobileModernHouse : House { public override void DrowDoor() { } public override void DrowWindow() { } public override void PlatformInit() { //這裡初始化構建移動端的現代化房屋所需要的移動端平臺的相關資訊 } } /// <summary> /// PC版經典房屋 /// </summary> public class PCClassicalHouse : House { public override void DrowDoor() { } public override void DrowWindow() { } public override void PlatformInit() { //這裡初始化構建PC版經典房屋所需要的PC平臺的相關資訊 } } /// <summary> /// 移動版經典房屋 /// </summary> public class MobileClassicalHouse : House { public override void DrowDoor() { } public override void DrowWindow() { } public override void PlatformInit() { //這裡初始化構建移動版經典房屋所需要的移動版平臺的相關資訊 } }
ok,這種設計雖然能很好的滿足需求,但是這裡只列舉了兩種平臺,如果之後需要支援更多的平臺,這種設計模式顯然不行,因為產生的類會原來越多.隨之維護的成本也越來越大.
so.分析程式碼,發現設計中有兩個變化點,一個是House,另一個是平臺,而上面的程式碼並沒有把平臺作為變化點抽離出來,所以需要將平臺抽離抽來,接下來,對程式碼進行重構.
思考:由於House的固有邏輯,使得House具有兩個維護的變化一一一個變化維度為"平臺的變化",另一個變化維度為"風格的變化".那麼如何解決這種維度的變化?如何利用OOP,來輕鬆地使得House以"平臺"和"風格"兩個方向變化?這就是橋接模式要解決的問題:
利用Bridge橋接模式重構後的程式碼如下:
#region 抽象 /// <summary> /// 房屋抽象 /// </summary> public abstract class House { protected HousePlatform _housePlatform; public House(HousePlatform housePlatform) { _housePlatform = housePlatform; } public HousePlatform HousePlatform => _housePlatform; /// <summary> /// 繪製窗戶 /// </summary> public abstract void DrowWindow(); /// <summary> /// 繪製門 /// </summary> public abstract void DrowDoor(); } /// <summary> /// 平臺抽象 /// </summary> public abstract class HousePlatform { public abstract HousePlatform Init(); } #endregion #region 實現 /// <summary> /// 現代化房屋 /// </summary> public class ModernHouse : House { private HousePlatform _platform; public ModernHouse(HousePlatform housePlatform) : base(housePlatform) { _platform = HousePlatform.Init(); } public override void DrowDoor() { //執行HousePlatform例項的一些方法,然後做自己的邏輯 } public override void DrowWindow() { } } /// <summary> /// 經典房屋 /// </summary> public class ClassicalHouse : House { private HousePlatform _platform; public ClassicalHouse(HousePlatform housePlatform) : base(housePlatform) { _platform = housePlatform.Init(); } public override void DrowDoor() { } public override void DrowWindow() { } } /// <summary> /// PC平臺 /// </summary> public class PCPlatform : HousePlatform { public override HousePlatform Init() { //執行PC平臺的初始化方法,返回一個PCPlatform物件例項供對應的房屋使用 return this.MemberwiseClone() as HousePlatform; } } /// <summary> /// 移動端平臺 /// </summary> public class MobilePlatform : HousePlatform { public override HousePlatform Init() { //執行移動端平臺的初始化方法,返回一個MobilePlatform物件例項供對應的房屋使用 return this.MemberwiseClone() as HousePlatform; } } #endregion
客戶端呼叫程式碼如下:
public class GameSystem { public void Build() { //構建了一個基於PC平臺的現代化房屋 var modernHouse = new ModernHouse(new PCPlatform()); modernHouse.DrowDoor(); modernHouse.DrowWindow(); } }
將變化點平臺也分離出來,並抽象出一個介面,並通過建構函式的方式將兩個變化點橋接到一起,可以理解為組合到一起,這就是橋接模式.
橋接模式使用的要點:
1、Bridge橋接模式一般是用在兩個變化劇烈的維度,如上面的房屋的風格和平臺的型別都是變化非常劇烈的,但如果有一個維度變化並不劇烈,則並需要使用橋接模式.
2、抽象和實現沿著各自緯度的變化,比如不同風格的房屋和不同的平臺.得到各個子類之後,便可以不同的方式組合它們,便可以得到不同平臺下的不同風格的房屋.
3、多繼承關係,可以考慮使用Bridge模式來實現.多繼承方案往往違背oop的單一職責.Bridge模式是比多繼承更好的選擇.
4、Bridge模式使用物件組合關係,解耦了抽象和實現之間固有的繫結關係,使得抽象(不同風格的房屋)和實現(不同的平臺)可以沿著各自的維度變化.
,