小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

設(shè)計模式(7) 橋接模式

 頭號碼甲 2021-07-16
  • 橋接模式的概念與實現(xiàn)
  • 為什么叫橋接模式
  • 橋接模式的適用場景

繼承是面向?qū)ο蟮娜筇匦灾?,但很多時候使用繼承的結(jié)果卻不盡如人意。除了人盡皆知的緊耦合問題外,有的時候還會導致子類的快速膨脹。

設(shè)想這樣一個場景:最初設(shè)計的時候有一個類型Product,但后來隨著新需求的出現(xiàn),X原因?qū)е铝怂淖兓?,X有兩種情況,則通過繼承需要創(chuàng)建兩個新的子類ProductX1,ProductX2,但后來有出現(xiàn)了Y因素也會導致Product的變化,如果Y有三種情況,則會出現(xiàn)ProductX1Y1,ProductX1Y2,ProductX1Y3...等,一共2*3=6個類。

使用這種繼承的方式,如果再出現(xiàn)新的變化因素,或者某個變化因素出現(xiàn)了新的情況,都會導致子類的快速膨脹,給維護帶來很大的挑戰(zhàn)。

造成這個問題的根本原因是類型在沿著多個維度變化。為了應(yīng)對變化,一般會通過抽象的方法,找到其中比較穩(wěn)定的部分,然后抽象其行為,令客戶程序依賴于抽象而不是具體實現(xiàn)。同樣的道理,當一個類型同時受到多個因素變化的影響時,也通過把每個因素抽象,讓類型依賴于一系列抽象因素的辦法盡量處理這個問題,這便是橋接模式解決問題的思路。

橋接模式的概念與實現(xiàn)

GOF對橋接模式的描述為:
Decouple an abstraction from its implementationso that the two can vary independently.
— Design Patterns : Elements of Reusable Object-Oriented Software
橋接模式將抽象部分與它的實現(xiàn)部分分離,使它們都可以獨立地變化。

橋接模式的UML類圖為
橋接模式 UML類圖

示例代碼:

public interface IImpl
{
    void OperationImpl();
}

public interface IAbstraction
{
    IImpl Implementor { get; set; }
    void Operation();
}
public class ConcreteImplementatorA : IImpl
{
    public void OperationImpl()
    {
        ...
    }
}

public class ConcreteImplementatorB : IImpl
{
    public void OperationImpl()
    {
        ...
    }
}

public class RefinedAbstration : IAbstraction
{
    public IImpl Implementor { get; set; }

    public void Operation()
    {
        Implementor.OperationImpl();
    }
}

這樣子看起來還是比較抽象,再舉個具體的例子汽車-道路,目前汽車有小汽車、巴士兩類,路有水泥路、石子路兩類,這樣“車在路上行駛”就會有四種情況,這個場景用橋接模式來描述的話可以是:
汽車類的抽象與實現(xiàn):

public interface IVehicle
{
    string Drive();
}

public class Car : IVehicle
{
    public string Drive()
    {
        return "Car";
    }
}

public class Bus : IVehicle
{
    public string Drive()
    {
        return "Bus";
    }
}

通過橋接模式關(guān)聯(lián)道路與汽車:

public abstract class Road
{
    protected IVehicle vehicle;
    public Road(IVehicle vehicle)
    {
        this.vehicle = vehicle;
    }

    public abstract string DriveOnRoad();
}

public class UnpavedRoad : Road
{
    public UnpavedRoad(IVehicle vehicle) : base(vehicle) { }
    public override string DriveOnRoad()
    {
        return vehicle.Drive() + " is on Unpaved Road";
    }
}

public class CementRoad : Road
{
    public CementRoad(IVehicle vehicle) : base(vehicle) { }
    public override string DriveOnRoad()
    {
        return vehicle.Drive() + " is on Cement Road";
    }
}

調(diào)用:

IVehicle vehicle = new Car();
Road road = new CementRoad(vehicle);
Console.WriteLine(road.DriveOnRoad());
// Car is on Cement Road
Speed speed = new FastSpeed(road);
Console.WriteLine(speed.DriveWithSpeed());
// Car is on Cement Road,

在這里Road依賴的是IVehivle抽象,具體的汽車實現(xiàn)在調(diào)用的時候決定。
對比直接繼承出四種類型的方式,這樣做的好處貌似并不明顯,還是需要四個類,而且更復雜,但如果汽車或者道路類型繼續(xù)增加,或者引入了別的變化因素,情況就不一樣了。

為什么叫橋接模式

有個疑惑是關(guān)于橋接模式的名稱的,為什么叫橋接模式呢?之前的工廠、適配器等名稱都挺形象的,但橋接模式好像有點不同,這要從橋接模式解決問題的思路說起,橋接模式更多的是提示我們面向?qū)ο蟮脑O(shè)計分解方式,可以概括為三步:

  • 第一步,把依賴具體變成依賴抽象。
  • 第二步,如果對象同時沿著多個維度變化,那就順次展開抽象因素。
  • 第三步,為每個抽象因素提供具體實現(xiàn)。

示意圖:
分解

到了第三步,就可以大概看出橋接模式的形象化表示了,IX、IY和IZ構(gòu)成連接部(被稱為支座),而每個具體類形成了一個個橋墩。
所以橋接模式,是以抽象之間的依賴為橋面、以具體實現(xiàn)為橋墩,建起了一座連接需求與實現(xiàn)的橋梁。

橋接模式的適用場景

  • 如果一個系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的聯(lián)系。
  • 設(shè)計要求實現(xiàn)化角色的任何改變不應(yīng)當影響客戶端,或者說實現(xiàn)化角色的改變對客戶端是完全透明的。
  • 一個構(gòu)件有多于一個的抽象化角色和實現(xiàn)化角色,系統(tǒng)需要它們之間進行動態(tài)耦合。
  • 雖然在系統(tǒng)中使用繼承是沒有問題的,但是由于抽象化角色和具體化角色需要獨立變化,設(shè)計要求需要獨立管理這兩者。

參考書籍:
王翔著 《設(shè)計模式——基于C#的工程化實現(xiàn)及擴展》

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多