標籤:設計模式 橋接模式 合成彙總原則 松耦合
橋接模式屬於結構型設計模式。
設計意圖:將抽象部分與實現部分分離,使它們都可以獨立的變化。
一看到設計意圖,大家可能有些發懵,我們看到的繼承和介面不都是抽象和實現分離的嗎?尤其是介面和抽象類別都是這樣的實現啊!那怎麼還有這麼個橋接的分離呢?
我們先來看個例子。
例如:汽車品牌內建導航儀,我們希望實現,每個品牌的導航儀都可以在任何一個牌子的汽車上安裝並啟動。
汽車品牌有兩個:寶馬、平治。
導航儀有三個牌子:神行者、北鬥、高德。
來看正常的設計,我們肯定是會這樣的採用繼承來實現每個組合的安裝和啟動處理的,每個品牌+導航都需要一個獨立的類來實現功能,但是這裡有個一個問題,如果我們再增加一個品牌那麼就意味著要再增加三個類,每增加一個品牌都是如此,這是一件太痛苦的事啊!所以能找到一種方式不用增加類就可以實現新品牌安裝並開啟導航儀的功能嗎?
來看下面的圖,我們將汽車品牌和導航儀品牌做一個組合。
如果能這樣組合,那每增加一個汽車品牌時,就只需要增加一個品牌類就好,這個品牌和之前的導航儀組合就可以了。
我們可以看出導航儀和汽車其實是一種彙總關係,也就是導航儀只是汽車的一部分,而這一部分不隨著汽車消亡而消失。所以他們之間是松耦合關係,彙總關係。
橋接模式是遵循了合成/彙總複用原則(稍後我們在介紹該原則),我們來看通用通用類圖。
Abstraction:定義抽象類別的介面,該介面中定義如何使用Implementor介面類型對象的方法。
RefinedAbstraction:實現由Abstraction定義的介面方法,可能會有自己的一些私人方法。
Implementor:定義Abstraction抽象的實現,這種實現是一種嫁接的關係,就像電腦主板和音效卡、顯卡的關係一樣,它可以是一個介面, Implementor介面提供Abstraction抽象介面需要的操作,而 Abstraction則定義了基於這些基本操作的較高層次的操作。
ConcreteImplementor:實現Implementor介面並定義它的具體實現。
讓我們來看執行個體代碼,通過執行個體代碼可以更好的理解橋接模式的神奇,它真的是實現可插拔式的模式。
package com.bridge;/** * 1:汽車品牌抽象類別,這個抽象類別主要是導航的安裝與啟動,其它的配件也可以在該類提供方法, * 但是為了開-閉原則,最好可以在另加其它介面。 * 2:橋接就是要實現插拔方式的調用,我們想一下主板和外掛程式,主板提供介面定義該介面的功能, * 由外掛程式來實現該介面的功能。這就是橋接的主要思想,抽象與實現分離。 * 3:該類定義了如何注入一個介面的方法install,並定義了如何操作注入介面的具體實現的方法open。 * 4:這裡其實可以使用介面,如果使用介面,那就更靈活,以後我再給大家寫一個多個介面的例子 * ,每個配件一個介面。這樣每個品牌的汽車可以實現多個介面也就可以增加不同的配件了。 * @author gaoxu * 實踐出真知! */public abstract class AbstractVehicleBrand {/**安裝導航方法 * @author gaoxu * @param n */public abstract void install(INavigator n);/**開啟導航 * 開啟導航是調用導航介面實作類別的方法,其實那個方法就是我們這個方法的延伸。 * @author gaoxu */public abstract void open();}</span>
<span style="font-size:14px;">package com.bridge;/** * @author gaoxu * 實踐出真知! */public class BMWVehicle extends AbstractVehicleBrand{//導航INavigator navigator = null;@Overridepublic void install(INavigator n) {navigator = n;}@Overridepublic void open() {navigator.work();}}
package com.bridge;/** * @author gaoxu * 實踐出真知! */public class BenzVehicle extends AbstractVehicleBrand{//導航INavigator navigator = null;@Overridepublic void install(INavigator n) {navigator = n;}@Overridepublic void open() {navigator.work();}}導航外掛程式的公用介面,定義了導航的行為方法。
package com.bridge;/** * @author gaoxu * 實踐出真知! */public interface INavigator {public void work();}
package com.bridge;public class SXZNavigator implements INavigator{@Overridepublic void work() {System.out.println("我是神行者導航!");}}
package com.bridge;public class BDNavigator implements INavigator{@Overridepublic void work() {System.out.println("我是北鬥導航!");}}
我們來看用戶端代碼
package com.bridge;public class Client {public static void main(String[] para){//我們現在是實現不同品牌的汽車,可以安裝不同牌子的導航,也就是把汽車和導航彙總了起來。//我們是通過橋接的方式完成了這種彙總,橋接方式比繼承的方式要更靈活,它是汽車與配件可 以獨立各自的發展。//我們可以實現的彙總關係:寶馬+北鬥,寶馬+神行者,平治+北鬥,平治+身形者//當然我們還可以給汽車配置更多不同的後裝配件例如:空氣淨化器等。INavigator bdNavigator = new BDNavigator();INavigator sxzNavigator = new SXZNavigator();//寶馬安裝北鬥導航AbstractVehicleBrand bmw = new BMWVehicle();bmw.install(bdNavigator);bmw.open();//平治安裝了神行者導航AbstractVehicleBrand benz = new BMWVehicle();benz.install(sxzNavigator);benz.open();}}
優點:把兩種都具有變化的分類實現獨立變化,真的是松耦合的典範。
使用範圍:多個具有變化的分類共同實現功能時易採用橋接模式。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
跟著執行個體學習設計模式(9)-橋接模式bridge(結構型)