23種設計模式之Bridge模式

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

可以看到調用很方便,類決定了什麼樣的咖啡(抽象),而參數決定了什麼樣的操作(行爲)。

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