java設計模式之一 橋接模式

xz43發表於2011-02-24

本文介紹設計模式中的橋接(Bridge)模式的概念,用法,以及實際應用中怎麼樣使用橋接模式進行開發。

Bridge模式的概念

Bridge 模式是構造型的設計模式之一。Bridge模式基於類的最小設計原則,透過使用封裝,聚合以及繼承等行為來讓不同的類承擔不同的責任。它的主要特點是把抽象(abstraction)與行為實現(implementation)分離開來,從而可以保持各部分的獨立性以及應對它們的功能擴充套件。

Bridge模式的應用場景

物件導向的程式設計(OOP)裡有類繼承(子類繼承父類)的概念,如果一個類或介面有多個具體實現子類,如果這些子類具有以下特性:
- 存在相對並列的子類屬性。
- 存在概念上的交叉。
- 可變性。
我們就可以用Bridge模式來對其進行抽象與具體,對相關類進行重構。

為了容易理解,我們舉例說明一下,比如汽車類(Car),假設有2個子類,卡車類(Truck)與公交車類(Bus),它們有[設定引擎]這個動作行為,透過不同引擎規格的設定,可以將它們設定為比如為1500cc(Car1500),和2000cc(Car2000)的車。
這樣,不管是1500cc的卡車還是2000cc的卡車,又或是1500cc的公交車還是2000cc的公交車,它們都可以是汽車類的子類,而且:
- 存在相對並列的子類屬性。汽車的種類,與汽車引擎規格是汽車的2個並列的屬性,沒有概念上的重複。
- 存在概念上的交叉。不管是卡車還是公交車,都有1500cc與2000cc引擎規格的車。
- 可變性。除了卡車,公交車之外,可能還有救火車;除了有1500cc與2000cc引擎規格的車之外,還可能有2500cc的車等等。

這樣一來,我們怎麼來設計汽車類呢?

方法一

透過繼承設計所有可能存在的子類。可能我們會想到下面的這種繼承關係:
汽車總類:Car
汽車子類 - 按種類分類:Bus,Truck
汽車子類 - 按引擎分類:Bus1500,Bus2000,Truck1500,Truck2000
這樣設定引擎這個動作就由各個子類加以實現。

但如果以後需要增加一種救火車(FireCar),以及增加一個引擎規格2500cc,需要實現的子類將會有:
Bus1500,Bus2000,Bus2500,Truck1500,Truck2000,Truck2500,FireCar1500,FireCar2000,FireCar2500 多達9個。
也就是說,這種設計方法,子類數目將隨幾何級數增長。
而且,Bus1500,Truck1500的引擎規格相同,它們的引擎設定動作應該是一樣的,但現在把它們分成不同的子類,難以避免執行重複的動作行為。

方法二

分別為Bus以及Truck實現設定不同引擎的方法
汽車總類:Car
汽車子類:Bus,Truck

然後在Bus類裡分別提供1500cc以及2000cc引擎的設定方法:
Bus extends Car {
    public setEngine1500cc();
    public setEngine2000cc();
}

在Truck類裡也分別提供1500cc以及2000cc引擎的設定方法:
Truck extends Car {
    public setEngine1500cc();
    public setEngine2000cc();
}

這種情況,子類的數量是被控制了。但一方面,如果每增加一種引擎規格,需要修改所有的汽車子類;另一方面,即使引擎的設定行為一樣,但是不同的汽車子類卻需要提供完全一樣的方法。

在實際的應用開發中,以上2種方法都會造成遷一發而動全身,而且會存在大量的重複程式碼。

Bridge模式可以很好的解決這類問題。

Client
    Bridge模式的使用者
Abstraction
    抽象類介面(介面或抽象類)
    維護對行為實現(Implementor)的引用
Refined Abstraction
    Abstraction子類
Implementor
    行為實現類介面 (Abstraction介面定義了基於Implementor介面的更高層次的操作)
ConcreteImplementor
    Implementor子類

Bridge模式的應用範例

我們來看看怎麼應用Bridge模式來設計汽車類。

抽象 - Abstraction類:汽車類及其子類:
Car:汽車總類
Truck:汽車子類 - 卡車類。
Bus:汽車子類 - 公交車類。

行為實現 - Implementor:汽車引擎設定的行為類及子類
SetCarEngine:汽車引擎的設定介面
SetCarEngine1500cc:設定1500cc引擎
SetCarEngine2000cc:設定2000cc引擎

程式碼:

package zieckey.designpatterns.study.bridge;

//測試

public class Client
{
    public static void main( String[] argv )
    {
        Engine engine1500 = new Engine1500CC();
        Engine engine2200 = new Engine2200CC();
       
        Vehicle bus1500 = new Bus( engine1500 );
        Vehicle bus2200 = new Bus( engine2200 );
        bus1500.setEngine();
        bus2200.setEngine();
       
        Vehicle truck1500 = new Truck( engine1500 );
        Vehicle truck2200 = new Truck( engine2200 );
        truck1500.setEngine();
        truck2200.setEngine();
    }
}

package zieckey.designpatterns.study.bridge;

/**
 *
 * 汽車類(Vehicle),假設有2個子類,卡車類(Truck)與公交車類(Bus),
 * 它們有[設定引擎]這個動作行為,透過不同引擎規格的設定,
 * 可以將它們設定為比如為1500cc(Car1500),和2000cc(Car2000)的車。
 * 這樣,不管是1500cc的卡車還是2000cc的卡車,又或是1500cc的公交車還是2000cc的公交車,它們都可以是汽車類的子類,而且:
 *     - 存在相對並列的子類屬性。汽車的種類,與汽車引擎規格是汽車的2個並列的屬性,沒有概念上的重複。
 *     - 存在概念上的交叉。不管是卡車還是公交車,都有1500cc與2000cc引擎規格的車。
 *     - 可變性。除了卡車,公交車之外,可能還有救火車;除了有1500cc與2000cc引擎規格的車之外,還可能有2500cc的車等等。
 *
 * @author
 * @since 2008/06/23
 */
public abstract class Vehicle
{
    private Engine engine;

    Vehicle( Engine engine )
    {
        this.setEngine( engine );
    }
   
    public abstract void setEngine();

    public void setEngine( Engine engine )
    {
        this.engine = engine;
    }

    public Engine getEngine()
    {
        return engine;
    }
}

package zieckey.designpatterns.study.bridge;

//Abstraction子類:這裡為汽車抽象類的子類

public class Bus extends Vehicle
{
    public Bus( Engine engine)
    {
        super( engine );
    }
   
    @Override
    public void setEngine()
    {
        System.out.print("Set Bus Engine: ");
        getEngine().setEngine();
    }
}

package zieckey.designpatterns.study.bridge;

//Abstraction子類:這裡為汽車抽象類的子類

public class Truck extends Vehicle
{
    public Truck( Engine engine )
    {
        super( engine );
    }

    @Override
    public void setEngine()
    {
        System.out.print("Set Truck Engine: ");
        getEngine().setEngine();
    }

}

package zieckey.designpatterns.study.bridge;

//汽車類的行為介面

public interface Engine
{
    public void setEngine();
}

package zieckey.designpatterns.study.bridge;

/** ConcreteImplementor */
//行為實現子類

public class Engine2200CC implements Engine
{

    public void setEngine()
    {
        System.out.println("engine 2200CC");
    }   
   
}

package zieckey.designpatterns.study.bridge;

/** ConcreteImplementor */
//行為實現子類

public class Engine1500CC implements Engine
{

    public void setEngine()
    {
        System.out.println("engine 1500CC");
    }   
   
}

 

小結:Bridge模式是一種抽象與其實現相分離的模式。它主要應用於:當事物是一組變化量,和對這些事物的操作方法(實現)也是一組變化量的情況,也就是說它們都是多變的。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-687882/,如需轉載,請註明出處,否則將追究法律責任。

相關文章