設計模式(十三)----結構型模式之橋接模式

2023-02-28 06:01:27

1 概述

現在有一個需求,需要建立不同的圖形,並且每個圖形都有可能會有不同的顏色。我們可以利用繼承的方式來設計類的關係:

我們可以發現有很多的類,假如我們再增加一個形狀或再增加一種顏色,就需要建立更多的類。

試想,在一個有多種可能會變化的維度的系統中,用繼承方式會造成類爆炸,擴充套件起來不靈活。每次在一個維度上新增一個具體實現都要增加多個子類。為了更加靈活的設計系統,我們此時可以考慮使用橋接模式。

定義:

將抽象與實現分離,使它們可以獨立變化。它是用組合關係代替繼承關係來實現,從而降低了抽象和實現這兩個可變維度的耦合度。

2 結構

橋接(Bridge)模式包含以下主要角色:

  • 抽象化(Abstraction)角色 :定義抽象類,幷包含一個對實現化物件的參照。下面中的OperatingSystem

  • 擴充套件抽象化(Refined Abstraction)角色 :是抽象化角色的子類,實現父類別中的業務方法,並通過組合關係呼叫實現化角色中的業務方法。

  • 實現化(Implementor)角色 :定義實現化角色的介面,供擴充套件抽象化角色呼叫。下面中的VidoeFile介面

  • 具體實現化(Concrete Implementor)角色 :給出實現化角色介面的具體實現。

3 案例

【例】視訊播放器

需要開發一個跨平臺視訊播放器,可以在不同作業系統平臺(如Windows、Mac、Linux等)上播放多種格式的視訊檔,常見的視訊格式包括RMVB、AVI、WMV等。該播放器包含了兩個維度,適合使用橋接模式。

類圖如下:

程式碼如下:

//視訊檔   實現化角色
public interface VideoFile {
    void decode(String fileName);
}
​
//avi檔案  具體實現化角色
public class AVIFile implements VideoFile {
    public void decode(String fileName) {
        System.out.println("avi視訊檔:"+ fileName);
    }
}
​
//rmvb檔案  具體實現化角色
public class REVBBFile implements VideoFile {
​
    public void decode(String fileName) {
        System.out.println("rmvb檔案:" + fileName);
    }
}
​
//作業系統版本  抽象角色
public abstract class OperatingSystemVersion {
​
    protected VideoFile videoFile;
​
    public OperatingSystemVersion(VideoFile videoFile) {
        this.videoFile = videoFile;
    }
​
    public abstract void play(String fileName);
}
​
//Windows版本  擴充套件抽象化角色
public class Windows extends OperatingSystem {
​
    public Windows(VideoFile videoFile) {
        super(videoFile);
    }
​
    public void play(String fileName) {
        videoFile.decode(fileName);
    }
}
​
//mac版本  擴充套件抽象化角色
public class Mac extends OperatingSystemVersion {
​
    public Mac(VideoFile videoFile) {
        super(videoFile);
    }
​
    public void play(String fileName) {
        videoFile.decode(fileName);
    }
}
​
//測試類
public class Client {
    public static void main(String[] args) {
        OperatingSystem os = new Windows(new AVIFile());
        os.play("戰狼3");
    }
}

好處:

  • 橋接模式提高了系統的可擴充性,在兩個變化維度中任意擴充套件一個維度,都不需要修改原有系統。

    如:如果現在還有一種視訊檔型別wmv,我們只需要再定義一個類實現VideoFile介面即可,其他類不需要發生變化。

  • 實現細節對客戶透明

4 使用場景

  • 當一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴充套件時。

  • 當一個系統不希望使用繼承或因為多層次繼承導致系統類的個數急劇增加時。

  • 當一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性時。避免在兩個層次之間建立靜態的繼承聯絡,通過橋接模式可以使它們在抽象層建立一個關聯關係。