Java設計模式-橋接模式 理論程式碼相結合

語言: CN / TW / HK

highlight: a11y-dark theme: cyanosis


這是我參與8月更文挑戰的第10天,活動詳情檢視:8月更文挑戰

繼Java設計模式-裝飾器模式後的橋接模式出來了,感興趣的話,就來看一看吧。

會了就當複習丫,不會來一起來看看吧。

很喜歡一句話:“八小時內謀生活,八小時外謀發展”

如果你也喜歡,讓我們一起堅持吧!!

共勉😁

校園一角

設計模式系列

一、橋接模式介紹

1)引入

​ 在現實生活中,某些類具有兩個或多個維度的變化,如圖形既可按形狀分,又可按顏色分。如何設計類似於 Photoshop 這樣的軟體,能畫不同形狀和不同顏色的圖形呢?如果用繼承方式,m 種形狀和 n 種顏色的圖形就有 m×n 種,不但對應的子類很多,而且擴充套件困難。

​ 在軟體系統中,某些型別由於自身的邏輯,它具有兩個或多個維度的變化,那麼如何應對這種“多維度的變化”?如何利用面向物件的技術來使得該型別能夠輕鬆的沿著多個方向進行變化,而又不引入額外的複雜度?這就要使用Bridge模式。(當然並不侷限於橋接模式)

2)概述

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

橋接模式將繼承關係轉化成關聯關係,它降低了類與類之間的耦合度,減少了系統中類的數量,也減少了程式碼量

將抽象部分與他的實現部分分離這句話不是很好理解,其實這並不是將抽象類與他的派生類分離,而是抽象類和它的派生類用來實現自己的物件。這樣還是不能理解的話。我們就先來認清什麼是抽象化,什麼是實現化,什麼是脫耦

抽象化:存在於多個實體中的共同的概念性聯絡,就是抽象化。作為一個過程,抽象化就是忽略一些資訊,從而把不同的實體當做同樣的實體對待。

實現化:抽象化給出的具體實現,就是實現化

脫耦:所謂耦合,就是兩個實體的行為的某種強關聯。而將它們的強關聯去掉,就是耦合的解脫,或稱脫耦。在這裡,脫耦是指將抽象化和實現化之間的耦合解脫開,或者說是將它們之間的強關聯改換成弱關聯。

兩個角色之間的繼承關係改為聚合關係,就是將它們之間的強關聯改換成為弱關聯。因此,橋樑模式中的所謂脫耦,就是指在一個軟體系統的抽象化和實現化之間使用組合/聚合關係而不是繼承關係,從而使兩者可以相對獨立地變化。這就是橋樑模式的用意。

3)模式結構

橋接模式的結構圖

由抽象化角色和修正抽象化角色組成的抽象化等級結構。

由實現化角色和兩個具體實現化角色所組成的實現化等級結構。

抽象化 (Abstraction)角色:抽象化給出的定義,並儲存一個對實現化物件的引用。

擴充套件抽象化(Refined Abstraction)角色:擴充套件抽象化角色,改變和修正父類對抽象化的定義。

實現化(Implementor)角色:這個角色給出實現化角色的介面,但不給出具體的實現。必須指出的是,這個介面不一定和抽象化角色的介面定義相同,實際上,這兩個介面可以非常不一樣。實現化角色應當只給出底層操作,而抽象化角色應當只給出基於底層操作的更高一層的操作。

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

4)使用場景

  • 不希望或不適用使用繼承的場景
  • 介面或抽象類不穩定的場景
  • 重用性要求較高的場景

二、橋接模式案例

2.1、案例

下面我們舉一個例子:

需要開發一個跨平臺視訊播放器,可以在不同作業系統平臺(如Windows、Mac、Linux等)上播放多種格式的視訊檔案,常見的視訊格式包括RMVB、AVI、WMV等。

該播放器包含了兩個維度,適合使用橋接模式。橋接模式的核心意圖就是把這些實現獨立出來,讓它們各自地變化,這就使得每種實現的變化不會影響其他實現,從而達到應對變化的目的。

圖解:

在這裡插入圖片描述

從上面這個圖可以看出,

兩個維度分別為:

  1. OperatingSystem就是抽象化角色,Windows和Mac是擴充套件化角色,
  2. VideoFile就是實現化角色,AVIFile和RMVBFile是具體實現化角色。

我都懂的,還是看下面👇程式碼的實現是咋樣的吧😁

2.2、程式碼實現

OperatingSystem:

```java public abstract class OperatingSystemVersion {

protected VideoFile videoFile;

public OperatingSystemVersion(VideoFile videoFile) {
    this.videoFile = videoFile;
}

public abstract void play(String fileName);

} ```

Windows和Mac是擴充套件化角色

```java public class Windows extends OperatingSystemVersion {

public Windows(VideoFile videoFile) {
    super(videoFile);
}

public void play(String fileName) {
    System.out.println("Windows正在播放:");
    videoFile.decode(fileName);
}

}

public class Mac extends OperatingSystemVersion {

public Mac(VideoFile videoFile) {
    super(videoFile);
}

@Override
public void play(String fileName) {
    System.out.println("Mac正在播放:");
    videoFile.decode(fileName);
}

} ```

VideoFile

java public interface VideoFile { void decode(String fileName); }

AVIFile和RMVBFile是具體實現化角色

```java public class REVBBFile implements VideoFile {

public void decode(String fileName) {
    System.out.println("rmvb檔案:" + fileName);
}

}

public class AVIFile implements VideoFile { @Override public void decode(String fileName) { System.out.println("avi視訊檔案:"+ fileName); } } ```

測試:

java public class Client { public static void main(String[] args) { OperatingSystemVersion os = new Mac(new AVIFile()); os.play("戰狼3"); /** * 輸出:Mac正在播放:avi視訊檔案:戰狼3 */ } }

這麼寫之後,無論是對於擴充套件OperatingSystem還是VideoFile方面,都可以獨立的擴充套件,非常的方便。也符合上👆文中對於橋接模式的定義:將抽象部分與實現部分分離,使它們可以獨立變化。它是用組合關係代替繼承關係來實現,從而降低了抽象和實現這兩個可變維度的耦合度

三、總結

優缺點:

橋接(Bridge)模式的優點是:

  • 抽象與實現分離,擴充套件能力強
  • 符合開閉原則
  • 符合合成複用原則
  • 其實現細節對客戶透明

缺點是:由於聚合關係建立在抽象層,要求開發者針對抽象化進行設計與程式設計,能正確地識別出系統中兩個獨立變化的維度,這增加了系統的理解與設計難度。

注意事項

  • 不要一涉及繼承就考慮該模式,儘可能把變化的因素封裝到最細、最小的邏輯單元中,避免風險擴散
  • 當發現類的繼承有n層時,可以考慮使用該模式

四、自言自語

你卷我卷,大家卷,什麼時候這條路才是個頭啊。😇(還是直接上天吧)

有時候也想停下來歇一歇,一直做一個事情,感覺挺難堅持的。😁

你好,如果你正巧看到這篇文章,並且覺得對你有益的話,就給個贊吧,讓我感受一下分享的喜悅吧,蟹蟹。🤗

如若有寫的有誤的地方,也請大家不嗇賜教!!

同樣如若有存在疑惑的地方,請留言或私信,定會在第一時間回覆你。

持續更新中