深入理解Java設(shè)計(jì)模式之橋接模式
一、什么是橋接模式
橋接模式(Bridge Pattern):將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。它是一種對(duì)象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式。
二、橋接模式的結(jié)構(gòu)

在橋接模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
Abstraction(抽象類):用于定義抽象類的接口,它一般是抽象類而不是接口,其中定義了一個(gè)Implementor(實(shí)現(xiàn)類接口)類型的對(duì)象并可以維護(hù)該對(duì)象,它與Implementor之間具有關(guān)聯(lián)關(guān)系,它既可以包含抽象業(yè)務(wù)方法,也可以包含具體業(yè)務(wù)方法。RefinedAbstraction(擴(kuò)充抽象類):擴(kuò)充由Abstraction定義的接口,通常情況下它不再是抽象類而是具體類,它實(shí)現(xiàn)了在Abstraction中聲明的抽象業(yè)務(wù)方法,在RefinedAbstraction中可以調(diào)用在Implementor中定義的業(yè)務(wù)方法。Implementor(實(shí)現(xiàn)類接口):定義實(shí)現(xiàn)類的接口,這個(gè)接口不一定要與Abstraction的接口完全一致,事實(shí)上這兩個(gè)接口可以完全不同,一般而言,Implementor接口僅提供基本操作,而Abstraction定義的接口可能會(huì)做更多更復(fù)雜的操作。Implementor接口對(duì)這些基本操作進(jìn)行了聲明,而具體實(shí)現(xiàn)交給其子類。通過關(guān)聯(lián)關(guān)系,在Abstraction中不僅擁有自己的方法,還可以調(diào)用到Implementor中定義的方法,使用關(guān)聯(lián)關(guān)系來替代繼承關(guān)系。ConcreteImplementor(具體實(shí)現(xiàn)類):具體實(shí)現(xiàn)Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同實(shí)現(xiàn),在程序運(yùn)行時(shí),ConcreteImplementor對(duì)象將替換其父類對(duì)象,提供給抽象類具體的業(yè)務(wù)操作方法。
三、橋接模式的使用場(chǎng)景
- 當(dāng)對(duì)象存在多種變化的因素時(shí),考慮對(duì)其變化的因素和場(chǎng)景進(jìn)行抽象,然后進(jìn)行橋接;如筆擁有不同的功能。
- 當(dāng)多個(gè)對(duì)象存在多種變化的因素時(shí),考慮將這部分變化的部分抽象出來再聚合進(jìn)來;比如不同品牌的電腦安裝不同的系統(tǒng)、使用不同的軟件等,相當(dāng)于將第一條進(jìn)行橫向擴(kuò)展,增加橋接的數(shù)量。
四、橋接模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
(1)分離抽象接口及其實(shí)現(xiàn)部分。橋接模式使用“對(duì)象間的關(guān)聯(lián)關(guān)系”解耦了抽象和實(shí)現(xiàn)之間固有的綁定關(guān)系,使得抽象和實(shí)現(xiàn)可以沿著各自的維度來變化。所謂抽象和實(shí)現(xiàn)沿著各自維度的變化,也就是說抽象和實(shí)現(xiàn)不再在同一個(gè)繼承層次結(jié)構(gòu)中,而是“子類化”它們,使它們各自都具有自己的子類,以便任何組合子類,從而獲得多維度組合對(duì)象。
(2)在很多情況下,橋接模式可以取代多層繼承方案,多層繼承方案違背了“單一職責(zé)原則”,復(fù)用性較差,且類的個(gè)數(shù)非常多,橋接模式是比多層繼承方案更好的解決方法,它極大減少了子類的個(gè)數(shù)。
(3)橋接模式提高了系統(tǒng)的可擴(kuò)展性,在兩個(gè)變化維度中任意擴(kuò)展一個(gè)維度,都不需要修改原有系統(tǒng),符合“開閉原則”。
缺點(diǎn):
(1)橋接模式的使用會(huì)增加系統(tǒng)的理解與設(shè)計(jì)難度,由于關(guān)聯(lián)關(guān)系建立在抽象層,要求開發(fā)者一開始就針對(duì)抽象層進(jìn)行設(shè)計(jì)與編程。
(2)橋接模式要求正確識(shí)別出系統(tǒng)中兩個(gè)獨(dú)立變化的維度,因此其使用范圍具有一定的局限性,如何正確識(shí)別兩個(gè)獨(dú)立維度也需要一定的經(jīng)驗(yàn)積累。
五、裝飾,橋接和適配器模式的異同
三者都是結(jié)構(gòu)型的設(shè)計(jì)模式,而且都存在依賴抽象的情況
適配器模式:
重點(diǎn)強(qiáng)調(diào)的是適配的功能。(適配器依賴抽象)
關(guān)鍵點(diǎn)是:
主體類和適配器類實(shí)現(xiàn)相同的接口A
- 主體類依賴適配器類
- 適配器類依賴抽象接口B
- 被適配的類實(shí)現(xiàn)抽象接口B
最終的效果就是,主體類可以使用之前不相關(guān)的被適配類中的某些功能。
橋接模式:
重點(diǎn)強(qiáng)調(diào)的是多維度的變化。(主體類直接依賴抽象)
關(guān)鍵點(diǎn)是:
- 主體類依賴抽象A
- 主體類具有多個(gè)不同的實(shí)現(xiàn)類
- 抽象A具有多個(gè)不同的實(shí)現(xiàn)類
最終的效果就是,主體類的實(shí)現(xiàn)類和抽象的實(shí)現(xiàn)類分別可以在兩個(gè)維度上進(jìn)行各自的變化。如果主體類依賴多個(gè)抽象,則維度進(jìn)行增加,方便擴(kuò)展。
裝飾器模式:
重點(diǎn)強(qiáng)調(diào)的是裝飾功能。(主體類不僅依賴抽象,而且實(shí)現(xiàn)該抽象接口)
關(guān)鍵點(diǎn)是:
- 抽象A具有多個(gè)具體子類
- 裝飾器類依賴抽象A
- 裝飾器類實(shí)現(xiàn)抽象A
- 裝飾器類存在不同子類
最終的效果就是,(裝飾器實(shí)現(xiàn)類)對(duì)(原抽象的子類)進(jìn)行某些方法的功能加強(qiáng)。
六、橋接模式的實(shí)現(xiàn)
首先抽象出電視機(jī),提供遙控器改變的行為方法。
/// <summary>
/// 電視機(jī),提供抽象方法
/// </summary>
public abstract class TV
{
public abstract void On();
public abstract void Off();
public abstract void tuneChannel();
}
創(chuàng)建具體的電視機(jī),繼承自抽象電視機(jī)類:
/// <summary>
/// 三星牌電視機(jī),重寫基類的抽象方法
/// </summary>
public class Samsung:TV
{
public override void On()
{
Console.WriteLine("三星牌電視機(jī)已經(jīng)打開了");
}
public override void Off()
{
Console.WriteLine("三星牌電視機(jī)已經(jīng)關(guān)掉了");
}
public override void tuneChannel()
{
Console.WriteLine("三星牌電視機(jī)換頻道");
}
}
/// <summary>
/// 長(zhǎng)虹牌電視機(jī),重寫基類的抽象方法
/// 提供具體的實(shí)現(xiàn)
/// </summary>
public class ChangHong : TV
{
public override void On()
{
Console.WriteLine("長(zhǎng)虹牌電視機(jī)已經(jīng)打開了");
}
public override void Off()
{
Console.WriteLine("長(zhǎng)虹牌電視機(jī)已經(jīng)關(guān)掉了");
}
public override void tuneChannel()
{
Console.WriteLine("長(zhǎng)虹牌電視機(jī)換頻道");
}
}
然后抽象出概覽中的遙控器,扮演抽象話的角色
/// <summary>
/// 抽象概念中的遙控器,扮演抽象化角色
/// </summary>
public abstract class RemoteControl
{
public TV implementor { get; set; }
/// <summary>
/// 開電視機(jī)
/// 這里抽象類中不再提供實(shí)現(xiàn)了,而是調(diào)用實(shí)現(xiàn)類中的實(shí)現(xiàn)
/// </summary>
public virtual void On()
{
implementor.On();
}
/// <summary>
/// 關(guān)電視機(jī)
/// </summary>
public virtual void Off()
{
implementor.Off();
}
/// <summary>
/// 換頻道
/// </summary>
public virtual void SetChannel()
{
implementor.tuneChannel();
}
}
創(chuàng)建具體遙控器類:這里面,我重寫了更換頻道的方法,其實(shí)還可以重寫其他的方法
/// <summary>
/// 具體遙控器類
/// </summary>
public class ConcreteRemote:RemoteControl
{
/// <summary>
/// 重寫更換頻道方法
/// </summary>
public override void SetChannel()
{
Console.WriteLine("重寫更換頻道方法");
base.SetChannel();
}
}
客戶端代碼:
static void Main(string[] args)
{
// 創(chuàng)建一個(gè)遙控器
RemoteControl remoteControl = new ConcreteRemote();
//長(zhǎng)虹電視機(jī)
remoteControl.implementor = new ChangHong();
remoteControl.On();
remoteControl.SetChannel();
remoteControl.Off();
Console.WriteLine();
// 三星牌電視機(jī)
remoteControl.implementor = new Samsung();
remoteControl.On();
remoteControl.SetChannel();
remoteControl.Off();
Console.Read();
}
這樣接實(shí)現(xiàn)了橋接模式的設(shè)計(jì),遙控器的功能實(shí)現(xiàn)方法不是在遙控器中去實(shí)現(xiàn)了,而是將實(shí)現(xiàn)部分用來另一個(gè)電視機(jī)類去封裝它,遙控器中只包含電視機(jī)類的一個(gè)引用,通過橋接模式,我們把抽象化和實(shí)現(xiàn)化部分分離開了,這樣可以很好應(yīng)對(duì)這兩方面的變化。
七、總結(jié)
橋接模式是一個(gè)非常有用的模式,在橋接模式中體現(xiàn)了很多面向?qū)ο笤O(shè)計(jì)原則的思想,包括“單一職責(zé)原則”、“開閉原則”、“合成復(fù)用原則”、“里氏代換原則”、“依賴倒轉(zhuǎn)原則”等。熟悉橋接模式有助于我們深入理解這些設(shè)計(jì)原則,也有助于我們形成正確的設(shè)計(jì)思想和培養(yǎng)良好的設(shè)計(jì)風(fēng)格。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Spring Cloud Alibaba和Dubbo融合實(shí)現(xiàn)
這篇文章主要介紹了Spring Cloud Alibaba和Dubbo融合實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
從內(nèi)存模型中了解Java final的全部細(xì)節(jié)
關(guān)于final關(guān)鍵字,它也是我們一個(gè)經(jīng)常用的關(guān)鍵字,可以修飾在類上、或者修飾在變量、方法上,以此看來定義它的一些不可變性!像我們經(jīng)常使用的String類中,它便是final來修飾的類,并且它的字符數(shù)組也是被final所修飾的。但是一些final的一些細(xì)節(jié)你真的了解過嗎2022-03-03
遞歸出現(xiàn)棧溢出stackoverflow的問題及解決
這篇文章主要介紹了關(guān)于遞歸出現(xiàn)棧溢出stackoverflow的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
Spring框架中Bean的三種配置和實(shí)例化方法總結(jié)
在Spring框架中,Bean的配置和實(shí)例化是很重要的基礎(chǔ)內(nèi)容,掌握各種配置方式,才能靈活管理Bean對(duì)象,本文將全面介紹Bean的別名配置、作用范圍配置,以及構(gòu)造器實(shí)例化、工廠實(shí)例化等方式2023-10-10
java中Socket設(shè)置超時(shí)時(shí)間的兩種方式
這篇文章主要介紹了java中Socket設(shè)置超時(shí)時(shí)間的兩種方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11

