設計模式之-橋接模式

定義:

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

橋接模式參與者

  • Abstraction:抽象。
  • RefinedAbstraction:被提煉的抽象。
  • Implementor:實現。
  • ConcreteImplementorA:具體實現。
  • ConcreteImplementorB:具體實現。

橋接模式基本代碼

Implementor類:github

namespace BridgePattern.BasicStructure
{
    abstract class Implementor
    {
        public abstract void Operation();
    }
}

ConcreteImplementorA類:編程

namespace BridgePattern.BasicStructure
{
    class ConcreteImplementorA : Implementor
    {
        public override void Operation()
        {
            Console.WriteLine("具體實現A的方法執行");
        }
    }
}

ConcreteImplementorB類:ide

namespace BridgePattern.BasicStructure
{
    class ConcreteImplementorB : Implementor
    {
        public override void Operation()
        {
            Console.WriteLine("具體實現B的方法執行");
        }
    }
}

Abstraction類:this

namespace BridgePattern.BasicStructure
{
    abstract class Abstraction
    {
        protected Implementor implementor;

        public void SetImplementor(Implementor implementor)
        {
            this.implementor = implementor;
        }
        public virtual void Operation()
        {
            implementor.Operation();
        }
    }
}

RefinedAbstraction類:spa

namespace BridgePattern.BasicStructure
{
    class RefinedAbstraction : Abstraction
    {
        public override void Operation()
        {
            implementor.Operation();
        }
    }
}

客戶端調用代碼:設計

    static void Main(string[] args)
    {
        try
        {
            {//BasicStructure
                Abstraction abstraction = new RefinedAbstraction();
                abstraction.SetImplementor(new ConcreteImplementorA());
                abstraction.Operation();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

結果以下:3d

用橋接模式實現手機品牌與手機軟件之間耦合帶來的問題

場景模擬:現有多種手機品牌,每種手機品牌的手機又都有某一些軟件,好比:遊戲軟件,通信錄,相機,聽歌......code

好比咱們有M和N兩種手機品牌,M手機和N手機都有X和Y兩種軟件。對象

咱們能夠這樣設計:

  • 定義一個品牌抽象類。
  • 分別定義繼承自品牌抽象類的M,N品牌類。
  • 分別定義繼承自M品牌類的X軟件類和Y軟件類,分別定義繼承自N品牌類的X軟件類和Y軟件類。

咱們還能夠這樣設計:

  • 定義一個軟件抽象類。
  • 分別定義繼承自軟件抽象類的X,Y軟件類。
  • 分別定義繼承自X軟件類的M品牌類和N品牌類,分別定義繼承自Y軟件類的M品牌類和N品牌類。

以上兩種方案均可以實現,但咱們仔細分析下,若是咱們再添加一個手機品牌呢和再添加一個軟件呢?

若是是第一個方案設計的話,再添加一個軟件的話,勢必會修改原來的代碼。

若是是第二個方案設計的話,再添加一個手機品牌的話,也會修改原來的代碼。

並且無論哪一種方案,當擴展一個新的品牌或軟件時,新增的類也很是的多,當時間愈來愈久,軟件和品牌愈來愈多時,你會發現你會崩潰的。

咱們用M表明手機品牌,用N表明軟件,這時候類的遞增規律是呈(M*N+M)或(M*N+N)遞增的。

接下來咱們就用橋接模式使得它呈M+N模式遞增

HandsetSoft(手機軟件)類——Implementor類

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手機軟件抽象類
    /// </summary>
    abstract class HandsetSoft
    {
        public abstract void Run(string name);
    }
}

HandsetGame(手機遊戲)類——ConcreteImplementorA類

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手機遊戲類
    /// </summary>
    class HandsetGame : HandsetSoft
    {
        public override void Run(string name)
        {
            Console.WriteLine($"{name}手機正在運行手機遊戲");
        }
    }
}

HandsetAddressList(手機通信錄)類——ConcreteImplementorB類

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手機通信錄類
    /// </summary>
    class HandsetAddressList : HandsetSoft
    {
        public override void Run(string name)
        {
            Console.WriteLine($"{name}手機正在運行手機通信錄");
        }
    }
}

HandsetBrand(手機品牌)類——Abstraction類

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 手機品牌類抽象類
    /// </summary>
    abstract class HandsetBrand
    {
        protected HandsetSoft handsetSoft;

        public void SetHandsetBrand(HandsetSoft handsetSoft)
        {
            this.handsetSoft = handsetSoft;
        }
        public virtual void Run(string name)
        {
            handsetSoft.Run(name);
        }
    }
}

Huawei(華爲)類——RefinedAbstraction類

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 華爲手機
    /// </summary>
    class Huawei : HandsetBrand
    {
        public override void Run(string name)
        {
            handsetSoft.Run(name);
        }
    }
}

Xiaomi(小米)類——RefinedAbstraction類

namespace BridgePattern.SituationSimulation
{
    /// <summary>
    /// 小米手機
    /// </summary>
    class Xiaomi : HandsetBrand
    {
        public override void Run(string name)
        {
            handsetSoft.Run(name);
        }
    }
}

客戶端調用代碼:

    static void Main(string[] args)
    {
        try
        {
            {//SituationSimulation
                HandsetBrand huawei = new Huawei();
                huawei.SetHandsetBrand(new HandsetGame());
                huawei.Run("華爲");

                HandsetBrand xiaomi = new Xiaomi();
                xiaomi.SetHandsetBrand(new HandsetGame());
                xiaomi.Run("小米");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

結果以下:

這樣就能夠實現(M+N)類遞增模式了,還很好的知足了"開閉原則"。

優勢:

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

缺點:

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

適用環境:

在如下狀況下可使用橋接模式:

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

總結:

  • 橋接模式將抽象部分與它的實現部分分離,使它們均可以獨立地變化。它是一種對象結構型模式,又稱爲柄體(Handle and Body)模式或接口(Interface)模式。
  • 橋接模式包含以下四個角色:抽象類中定義了一個實現類接口類型的對象並能夠維護該對象;擴充抽象類擴充由抽象類定義的接口,它實現了在抽象類中定義的抽象業務方法,在擴充抽象類中能夠調用在實現類接口中定義的業務方法;實現類接口定義了實現類的接口,實現類接口僅提供基本操做,而抽象類定義的接口可能會作更多更復雜的操做;具體實現類實現了實現類接口而且具體實現它,在不一樣的具體實現類中提供基本操做的不一樣實現,在程序運行時,具體實現類對象將替換其父類對象,提供給客戶端具體的業務操做方法。
  • 在橋接模式中,抽象化(Abstraction)與實現化(Implementation)脫耦,它們能夠沿着各自的維度獨立變化。
  • 橋接模式的主要優勢是分離抽象接口及其實現部分,是比多繼承方案更好的解決方法,橋接模式還提升了系統的可擴充性,在兩個變化維度中任意擴展一個維度,都不須要修改原有系統,實現細節對客戶透明,能夠對用戶隱藏實現細節;其主要缺點是增長系統的理解與設計難度,且識別出系統中兩個獨立變化的維度並非一件容易的事情。
  • 橋接模式適用狀況包括:須要在構件的抽象化角色和具體化角色之間增長更多的靈活性,避免在兩個層次之間創建靜態的繼承聯繫;抽象化角色和實現化角色能夠以繼承的方式獨立擴展而互不影響;一個類存在兩個獨立變化的維度,且這兩個維度都須要進行擴展;設計要求須要獨立管理抽象化角色和具體化角色;不但願使用繼承或由於多層次繼承致使系統類的個數急劇增長的系統。

 

源代碼地址:https://github.com/houzhenhuang/DesignPattern

相關文章
相關標籤/搜索