Bridge定義 :
將抽象和行爲劃分開來,各自獨立,但能動態的結合.
爲什麼使用?
通常,當一個抽象類或接口有多個具體實現,這些concrete之間關係可能有以下兩種:
1. 這多個具體實現之間恰好是並列的,如前面舉例,打樁,有兩個concrete class:方形樁和圓形樁;這兩個形狀上的樁是並列的,沒有概念上的重複,那麼我們只要使用繼承就可以了.
2.實際應用上,常常有可能在這多個concrete class之間有概念上重疊.那麼需要我們把抽象共同部分和行爲共同部分各自獨立開來,原來是準備放在一個接口裏,現在需要設計兩個接口,分別放置抽象和行爲.
例如,一杯咖啡爲例,有中杯和大杯之分,同時還有加奶 不加奶之分. 如果用單純的繼承,這四個具體實現之間有概念重疊,因爲有中杯加奶,也有中杯不加奶, 如果再在中杯這一層再實現兩個繼承,很顯然混亂,擴展性極差.那我們使用Bridge模式來實現它.
如何實現?
以上面提到的咖啡 爲例. 我們原來打算只設計一個接口,使用Bridge模式後,我們需要將抽象和行爲分開,加奶和不加奶屬於行爲,我們將它們抽象成一個專門的行爲接口:
public interface CoffeeImpl {
public String pourCoffeeImpl();
}
下面兩個是行爲的具體的實現子類
加奶
public class MilkCoffeeImpl implements CoffeeImpl {
public String pourCoffeeImpl() {
System.out.println("add milk");
return "add milk";
}
}
不加奶
public class FragrantCoffeeImpl implements CoffeeImpl {
public String pourCoffeeImpl() {
System.out.println("no milk");
return "no milk";
}
}
下面是咖啡的抽象父類,也就是區分大杯和中杯
public abstract class Coffee {
CoffeeImpl coffeeImpl;
public CoffeeImpl getCoffeeImpl() {
return coffeeImpl;
}
public void setCoffeeImpl(String way) {
this.coffeeImpl = ActionFactory.createCoffeeImpl(way);
}
public abstract void pourCoffee();
}
下面是2個抽象的具體實現子類
大杯
public class BigCoffee extends Coffee {
public BigCoffee(String way) {
pourCoffee();
this.setCoffeeImpl(way);
this.coffeeImpl.pourCoffeeImpl();
}
@Override
public void pourCoffee() {
System.out.print("Big coffee ");
}
}
中杯
public class MiddleCoffee extends Coffee {
public MiddleCoffee(String way) {
pourCoffee();
this.setCoffeeImpl(way);
this.coffeeImpl.pourCoffeeImpl();
}
@Override
public void pourCoffee() {
System.out.print("Middle coffee ");
}
}
下面是一個簡單工廠,用來動態確定咖啡的行爲,究竟是加奶還是不加奶,當然可以使用自己定義的方法來實現這個功能,這裏我選擇簡單工廠。
public class ActionFactory {
public static CoffeeImpl createCoffeeImpl(String way) {
if("milk".equals(way)) {
return new MilkCoffeeImpl();
} else if("fragrant".equals(way)) {
return new FragrantCoffeeImpl();
} else {
return null;
}
}
}
到此爲止,bridge模式就完成了,讀者可以很方便的自己試試着這個基礎上添加自己的咖啡抽象,比如小杯咖啡,還能添加咖啡行爲,比如加糖不加糖,記得需要對簡單工廠進行修改。
最後就是測試類
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
//中杯不加奶
Coffee coffee1 = new MiddleCoffee("fragrant");
//大杯加奶
Coffee coffee2 = new BigCoffee("milk");
//中杯加奶
Coffee coffee3 = new MiddleCoffee("milk");
//大杯不加奶
Coffee coffee4 = new BigCoffee("fragrant");
}
}
完成了,輸出結果是:
Middle coffee no milk
Big coffee add milk
Middle coffee add milk
Big coffee no milk
可以看到調用很方便,類決定了什麼樣的咖啡(抽象),而參數決定了什麼樣的操作(行爲)。