Java橋模式(Bridge模式)

來源:互聯網
上載者:User

標籤:

Bridge定義:將抽象和行為劃分開來,各自獨立,但能動態結合。為什麼使用橋模式通常,當一個抽象類別或介面有多個具體實現(concrete subclass),這些concrete之間關係可能有以下兩種:
  • 這多個具體實現之間恰好是並列的,如前面舉例,打樁,有兩個concrete class:方形樁和圓形樁;這兩個形狀上的樁是並列的,沒有概念上的重複,那麼我們只要使用繼承就可以了。
  • 實際應用上,常常有可能在這多個concrete class之間有概念上重疊。那麼需要我們把抽象共同部分和行為共同部分各自獨立開來,原來是準備放在一個介面裡,現在需要設計兩個介面,分別放置抽象和行為。

例如,一杯咖啡為例,有中杯和大杯之分,同時還有加奶 不加奶之分。如果用單純的繼承,這四個具體實現(中杯 大杯 加奶 不加奶)之間有概念重疊,因為有中杯加奶,也有中杯不加奶,如果再在中杯這一層再實現兩個繼承,很顯然混亂,擴充性極差。那我們使用Bridge模式來實現它。如何?橋模式以上面提到的咖啡 為例。我們原來打算只設計一個介面(抽象類別),使用Bridge模式後,我們需要將抽象和行為分開,加奶和不加奶屬於行為,我們將它們抽象成一個專門的行為介面。

先看看抽象部分的介面代碼:
public abstract class Coffee{
 CoffeeImp coffeeImp;
 public void setCoffeeImp() {
  this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
 }
 public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}
 public abstract void pourCoffee();
}
其中CoffeeImp 是加不加奶的行為介面,看其代碼如下:
public abstract class CoffeeImp{
 public abstract void pourCoffeeImp();
}

現在我們有了兩個抽象類別,下面我們分別對其進行繼承,實現concrete class://中杯
public class MediumCoffee extends Coffee{
 public MediumCoffee() {setCoffeeImp();}
 public void pourCoffee(){
  CoffeeImp coffeeImp = this.getCoffeeImp();
  //我們以重複次數來說明是沖中杯還是大杯 ,重複2次是中杯
  for (int i = 0; i < 2; i++){
   coffeeImp.pourCoffeeImp();
  }
 }
}

//大杯
public class SuperSizeCoffee extends Coffee{
 public SuperSizeCoffee() {setCoffeeImp();}
 public void pourCoffee(){
  CoffeeImp coffeeImp = this.getCoffeeImp();
  //我們以重複次數來說明是沖中杯還是大杯 ,重複5次是大杯
  for (int i = 0; i < 5; i++){
   coffeeImp.pourCoffeeImp();
  }
 }
}上面分別是中杯和大杯的具體實現.下面再對行為CoffeeImp進行繼承://加奶
public class MilkCoffeeImp extends CoffeeImp{
 MilkCoffeeImp() {}
 public void pourCoffeeImp(){
  System.out.println("加了美味的牛奶");
 }
}

//不加奶
public class FragrantCoffeeImp extends CoffeeImp{
 FragrantCoffeeImp() {}
 public void pourCoffeeImp(){
  System.out.println("什麼也沒加,清香");
 }
}Bridge模式的基本架構我們已經搭好了,別忘記定義中還有一句:動態結合,我們現在可以喝到至少四種咖啡:
  1. 中杯加奶
  2. 中杯不加奶
  3. 大杯加奶
  4. 大杯不加奶

看看是如何動態結合的,在使用之前,我們做個準備工作,設計一個單態類(Singleton)用來hold當前的CoffeeImp:public class CoffeeImpSingleton{
 private static CoffeeImp coffeeImp;
 public CoffeeImpSingleton(CoffeeImp coffeeImpIn)
 {this.coffeeImp = coffeeImpIn;}
 public static CoffeeImp getTheCoffeeImp(){
  return coffeeImp;
 }
}看看中杯加奶 和大杯加奶 是怎麼出來的://拿出牛奶
CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new MilkCoffeeImp());

//中杯加奶
MediumCoffee mediumCoffee = new MediumCoffee();
mediumCoffee.pourCoffee();

//大杯加奶
SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();
superSizeCoffee.pourCoffee();注意:Bridge模式的執行類如CoffeeImp和Coffee是一對一的關係,正確建立CoffeeImp是該模式的關鍵。Bridge模式在EJB中的應用EJB中有一個Data Access Object (DAO)模式,這是將商業邏輯和具體資料資源分開的,因為不同的資料庫有不同的資料庫操作。將操作不同資料庫的行為獨立抽象成一個行為介面DAO,如下:
  • Business Object (類似Coffee)
    實現一些抽象的商業操作:如尋找一個使用者下所有的訂單。涉及資料庫操作都使用DAOImplementor。
     
  • Data Access Object (類似CoffeeImp)
    一些抽象的對資料庫資源操作。
     
  • DAOImplementor 如OrderDAOCS, OrderDAOOracle, OrderDAOSybase(類似MilkCoffeeImp FragrantCoffeeImp)
    具體的資料庫操作,如"INSERT INTO "等語句,OrderDAOOracle是Oracle OrderDAOSybase是Sybase資料庫。
     
  • 資料庫 (Cloudscape, Oracle, or Sybase database via JDBC API)


橋接模式  概述
    將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
  適用性
    1.你不希望在抽象和它的實現部分之間有一個固定的綁定關係。      例如這種情況可能是因為,在程式運行時刻實現部分應可以被選擇或者切換。    2.類的抽象以及它的實現都應該可以通過產生子類的方法加以擴充。      這時Bridge模式使你可以對不同的抽象介面和實現部分進行組合,並分別對它們進行擴充。    3.對一個抽象的實現部分的修改應對客戶不產生影響,即客戶的代碼不必重新編譯。    4.正如在意圖一節的第一個類圖中所示的那樣,有許多類要產生。      這樣一種類階層說明你必須將一個對象分解成兩個部分。    5.你想在多個對象間共用實現(可能使用引用計數),但同時要求客戶並不知道這一點。
  參與者
    1.Abstraction      定義抽象類別的介面。      維護一個指向Implementor類型對象的指標。    2.RefinedAbstraction      擴充由Abstraction定義的介面。    3.Implementor      定義實作類別的介面,該介面不一定要與Abstraction的介面完全一致。      事實上這兩個介面可以完全不同。      一般來講,Implementor介面僅提供基本操作,而Abstraction則定義了基於這些基本操作的較高層次的操作。    4.ConcreteImplementor      實現Implementor介面並定義它的具體實現。
  類圖   例子 Abstraction
public abstract class Person {    private Clothing clothing;        private String type;    public Clothing getClothing() {        return clothing;    }    public void setClothing() {        this.clothing = ClothingFactory.getClothing();    }        public void setType(String type) {        this.type = type;    }        public String getType() {        return this.type;    }        public abstract void dress();}
RefinedAbstraction
public class Man extends Person {        public Man() {        setType("男人");    }        public void dress() {        Clothing clothing = getClothing();        clothing.personDressCloth(this);    }}
public class Lady extends Person {    public Lady() {        setType("女人");    }        public void dress() {        Clothing clothing = getClothing();        clothing.personDressCloth(this);    }}
Implementor
public abstract class Clothing {    public abstract void personDressCloth(Person person);}
ConcreteImplementor
public class Jacket extends Clothing {    public void personDressCloth(Person person) {        System.out.println(person.getType() + "穿馬甲");    }}
public class Trouser extends Clothing {    public void personDressCloth(Person person) {        System.out.println(person.getType() + "穿褲子");    }}
Test
public class Test {    public static void main(String[] args) {                Person man = new Man();                Person lady = new Lady();                Clothing jacket = new Jacket();                Clothing trouser = new Trouser();                jacket.personDressCloth(man);        trouser.personDressCloth(man);        jacket.personDressCloth(lady);        trouser.personDressCloth(lady);    }}
result
男人穿馬甲男人穿褲子女人穿馬甲女人穿褲子


Java橋模式(Bridge模式)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.