設計模式之-Bridge-- 橋接模式

Bridge模式也叫橋接模式,是由GoF提出的23種軟件設計模式的一種。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的車等等。

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

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


2,方法二:分別爲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模式可以很好的解決這類問題。
我們先看看Bridge模式的類圖描述:

[圖:出自wikipedia.org]

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

Bridge模式的應用範例

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

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

行爲實現 - Implementor:汽車引擎設置的行爲類及子類
SetCarEngine:汽車引擎的設置接口
SetCarEngine1500cc:設置1500cc引擎
SetCarEngine2000cc:設置2000cc引擎

Client類:使用Bridge模式
Client:測試

代碼:

  1. //測試   
  2. public   class  Client {  
  3.   
  4.     public   static   void  main(String[] args) {  
  5.         SetCarEngine carEngine1500cc = new  SetCarEngine1500cc();  
  6.         SetCarEngine carEngine2000cc = new  SetCarEngine2000cc();  
  7.           
  8.         Car truck1500cc = new  Truck(carEngine1500cc);  
  9.         Car truck2000cc = new  Truck(carEngine2000cc);  
  10.           
  11.         truck1500cc.setEngine();  
  12.         truck2000cc.setEngine();  
  13.           
  14.         Car bus1500cc = new  Bus(carEngine1500cc);  
  15.         Car bus2000cc = new  Bus(carEngine2000cc);  
  16.           
  17.         bus1500cc.setEngine();  
  18.         bus2000cc.setEngine();  
  19.     }  
  20.   
  21. }  
  22.   
  23.   
  24. /** "Abstraction" */   
  25. //汽車類的抽象   
  26. abstract   class  Car {  
  27.     SetCarEngine setCarEngine;  
  28.       
  29.     public   abstract   void  setEngine();  
  30. }  
  31.   
  32. /** Refined Abstraction */   
  33. //Abstraction子類:這裏爲汽車抽象類的子類   
  34. class  Truck  extends  Car {  
  35.     public  Truck(SetCarEngine setCarEngine) {  
  36.         this .setCarEngine = setCarEngine;  
  37.     }  
  38.       
  39.     public   void  setEngine() {  
  40.         System.out.print("Set Truck Engine: " );  
  41.           
  42.         setCarEngine.setEngine();  
  43.     }  
  44. }  
  45.   
  46. class  Bus  extends  Car {  
  47.     public  Bus(SetCarEngine setCarEngine) {  
  48.         this .setCarEngine = setCarEngine;  
  49.     }  
  50.       
  51.     public   void  setEngine() {  
  52.         System.out.print("Set Bus Engine: " );  
  53.         setCarEngine.setEngine();  
  54.     }  
  55. }  
  56.   
  57.   
  58. /** "Implementor" */   
  59. //汽車類的行爲實現   
  60. interface  SetCarEngine {  
  61.     public   void  setEngine();  
  62. }  
  63.   
  64. /** ConcreteImplementor */   
  65. //行爲實現子類   
  66. class  SetCarEngine1500cc  implements  SetCarEngine {  
  67.     public   void  setEngine() {  
  68.         System.out.println("1500cc" );  
  69.     }  
  70. }  
  71.   
  72. class  SetCarEngine2000cc  implements  SetCarEngine {  
  73.     public   void  setEngine() {  
  74.         System.out.println("2000cc" );  
  75.     }  
  76. }  
//測試
public class Client {

    public static void main(String[] args) {
        SetCarEngine carEngine1500cc = new SetCarEngine1500cc();
        SetCarEngine carEngine2000cc = new SetCarEngine2000cc();
        
        Car truck1500cc = new Truck(carEngine1500cc);
        Car truck2000cc = new Truck(carEngine2000cc);
        
        truck1500cc.setEngine();
        truck2000cc.setEngine();
        
        Car bus1500cc = new Bus(carEngine1500cc);
        Car bus2000cc = new Bus(carEngine2000cc);
        
        bus1500cc.setEngine();
        bus2000cc.setEngine();
    }

}


/** "Abstraction" */
//汽車類的抽象
abstract class Car {
    SetCarEngine setCarEngine;
    
    public abstract void setEngine();
}

/** Refined Abstraction */
//Abstraction子類:這裏爲汽車抽象類的子類
class Truck extends Car {
    public Truck(SetCarEngine setCarEngine) {
        this.setCarEngine = setCarEngine;
    }
    
    public void setEngine() {
        System.out.print("Set Truck Engine: ");
        
        setCarEngine.setEngine();
    }
}

class Bus extends Car {
    public Bus(SetCarEngine setCarEngine) {
        this.setCarEngine = setCarEngine;
    }
    
    public void setEngine() {
        System.out.print("Set Bus Engine: ");
        setCarEngine.setEngine();
    }
}


/** "Implementor" */
//汽車類的行爲實現
interface SetCarEngine {
    public void setEngine();
}

/** ConcreteImplementor */
//行爲實現子類
class SetCarEngine1500cc implements SetCarEngine {
    public void setEngine() {
        System.out.println("1500cc");
    }
}

class SetCarEngine2000cc implements SetCarEngine {
    public void setEngine() {
        System.out.println("2000cc");
    }
}



執行Client,輸出結果:
C:/Bridge>javac *.java
C:/Bridge>java Client
Set Truck Engine: 1500cc
Set Truck Engine: 2000cc
Set Bus Engine: 1500cc
Set Bus Engine: 2000cc
C:/Bridge>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章