Java解讀--橋接Bridge
1、核心意圖:
將抽象部分和實現部分分離,使它們都可以獨立的變化。
該模式的目標是通過把高層的抽象和底層的實現分開,分別構建自己的類層次結構,并通過實現部分的接口將兩部分進行橋接,從而達到高層抽象和底層實現可以獨立的方便擴展的目的。其核心是分離,和委托。
?
2、身邊實例:
Java語言的一個非常重要的特點是平臺的無關性,對于一般的高級語言所編寫的程序,如果要在不同的平臺上運行,為了適應不同平臺所帶來的指令集及數據類型等所帶來的差異,至少需要編譯成不同的目標代碼。
Java語言通過Java虛擬機實現了平臺的無關性,虛擬機通過對底層平臺指令集及數據類型等進行統一的抽象,針對不同的平臺用不同的虛擬機進行實現,這樣Java應用程序就可以通過編譯成符合虛擬機規范的字節碼文件,而在不同的平臺上都能正確運行。
這里的虛擬機正是橋接模式一個很好的展示,它隔離了底層實現(指令/數據類型等)和高層的應用程序,對于新開發的每個Java應用程序,都只需要編譯一次;而對于一個新平臺的支持,也僅需提供一個相應的Java虛擬機,就可以使所有應用系統正確運行。
Java應用程序及虛擬機的大體結構圖如下:
?

3、動機簡述:
在該模式的動機中,描述了一個平臺可移植的用戶界面工具箱,在該工具箱中會有多種窗口Window類型,為了實現平臺的可移植性,把窗口的實現部分從窗口類型中抽取出來,構成一個獨立的窗口實現WindowImp類層次,從而使得抽象窗口和窗口實現都可以獨立變化,以便于支持新的窗口類型和平臺實現。
?
4、模式效果:
橋接Bridge模式有兩個主要效果:1)通過分離抽象部分和實現部分,使兩者可以獨立變化;2)向客戶隱藏了實現部分,從而當需要擴展/更改實現部分時,不需要重新編譯客戶代碼。
對于效果1),當抽象部分和實現部分比較多樣時,可以顯著的減少類的種類,并提高代碼的靈活性。假定高層抽象和底層實現分別有5種類型,如果不采用橋接模式,而用繼承實現,那么就需要5*5=25個類(另有一個抽象類);如果采用橋接模式,將抽象部分和實現部分分離,就只需要5+5=10個類就可以(另有兩個抽象類),兩種實現的類如以下表格中所示:
?
繼承方式實現:
?
|
Implementor
|
|||||
Imp1
|
Imp2
|
Imp3
|
Imp4
|
Imp5
|
||
Abstraction
|
Abs1
|
Abs1Imp1
|
Abs1Imp2
|
Abs1Imp3
|
Abs1Imp4
|
Abs1Imp5
|
Abs2
|
Abs2Imp1
|
Abs2Imp2
|
Abs2Imp3
|
Abs2Imp4
|
Abs2Imp5
|
|
Abs3
|
Abs3Imp1
|
Abs3Imp2
|
Abs3Imp3
|
Abs3Imp4
|
Abs3Imp5
|
|
Abs4
|
Abs4Imp1
|
Abs4Imp2
|
Abs4Imp3
|
Abs4Imp4
|
Abs4Imp5
|
|
Abs5
|
Abs5Imp1
|
Abs5Imp2
|
Abs5Imp3
|
Abs5Imp4
|
Abs5Imp5
|
?
橋接模式實現:
?
|
Implementor
|
|||||
Imp1
|
Imp2
|
Imp3
|
Imp4
|
Imp5
|
||
Abstraction
|
Abs1
|
通過橋接關聯
|
||||
Abs2
|
||||||
Abs3
|
||||||
Abs4
|
||||||
Abs5
|
?
5、Java代碼示例:
下面代碼演示了一個支持不同平臺的圖形對象應用,圖形Shape有多種類型,如三角形正方形等,為了在不同平臺中實現圖形的繪制,把實現部分進行了分離,構成了ShapeImp類層次結構,包括在Windows中的ShapeImpWin,和Unix中的ShapeImpUnix,類結構圖如下:
?

代碼清單如下:
類Point,同上一篇文章《設計模式》之Java解讀--適配器Adapter中所示,表示畫面中的一個點坐標
?
package?qinysong.pattern.bridge;


public?class?Point?...{

??private?int?coordinateX;
??private?int?coordinateY;


??public?Point(int?coordinateX,?int?coordinateY)...{
????this.coordinateX?=?coordinateX;
????this.coordinateY?=?coordinateY;
??}

??public?String?toString()...{
????return?"Point[x="?+?coordinateX?+?",y="?+?coordinateY?+?"]";
??}

??public?int?getCoordinateX()?...{
????return?coordinateX;
??}

??public?int?getCoordinateY()?...{
????return?coordinateY;
??}
}




























?
類ShapeImp,實現接口(對應Implementor),這里只是畫一條直線
?
package?qinysong.pattern.bridge.implement;

import?qinysong.pattern.bridge.Point;


public?interface?ShapeImp?...{
??public?void?drawLine(Point?startPoint,?Point?endPoint);
}










?
類ShapeImpWin,實現接口的Windows實現類(對應ConcreteImplementor)
?
package?qinysong.pattern.bridge.implement;

import?qinysong.pattern.bridge.Point;


public?class?ShapeImpWin?implements?ShapeImp?...{


??/**?*//**
???*?實現ShapeImp接口方法
???*?@param?startPoint?Point
???*?@param?endPoint?Point
???*/

??public?void?drawLine(Point?startPoint,?Point?endPoint)?...{
????System.out.println("ShapeImpWin.drawLine?startPoint="?+?startPoint?+?",endPoint="?+?endPoint);
??}
}




















?
類ShapeImpUnix,實現接口的Unix實現類(對應ConcreteImplementor)
?
package?qinysong.pattern.bridge.implement;

import?qinysong.pattern.bridge.Point;


public?class?ShapeImpUnix?implements?ShapeImp?...{


??/**?*//**
???*?實現ShapeImp接口方法
???*?@param?startPoint?Point
???*?@param?endPoint?Point
???*/

??public?void?drawLine(Point?startPoint,?Point?endPoint)?...{
????System.out.println("ShapeImpUnix.drawLine?startPoint="?+?startPoint?+?",endPoint="?+?endPoint);
??}
}




















?
類Shape,圖形抽象類(對應Abstraction),具體類型包括三角形、正方形等
?
package?qinysong.pattern.bridge.abstraction;

import?qinysong.pattern.bridge.implement.ShapeImp;
import?qinysong.pattern.bridge.ShapeImpFactory;


public?abstract?class?Shape?...{

??protected?ShapeImp?shapeImp;

??protected?void?initShapeImp()...{
????shapeImp?=?ShapeImpFactory.getShapeImp();
??}

??//定義圖形抽象類的接口方法
??public?abstract?void?drawShape();

}




















?
類Triangle,三角形(對應RefinedAbstraction)
?
package?qinysong.pattern.bridge.abstraction;

import?qinysong.pattern.bridge.Point;


public?class?Triangle?extends?Shape...{

??//實現抽象圖形類Shape接口方法,繪制一個三角形

??public?void?drawShape()?...{
????System.out.println("Triangle.drawShape?繪制一個三角形...");
????initShapeImp();
????shapeImp.drawLine(new?Point(0,0),?new?Point(10,0));
????shapeImp.drawLine(new?Point(0,0),?new?Point(5,10));
????shapeImp.drawLine(new?Point(5,10),?new?Point(10,0));
??}
}



















?
類Square,正方形(對應RefinedAbstraction)
?
package?qinysong.pattern.bridge.abstraction;

import?qinysong.pattern.bridge.Point;


public?class?Square?extends?Shape...{

??//實現抽象圖形類Shape接口方法,繪制一個正方形

??public?void?drawShape()?...{
????System.out.println("Square.drawShape?繪制一個正方形...");
????initShapeImp();
????shapeImp.drawLine(new?Point(0,0),?new?Point(10,0));
????shapeImp.drawLine(new?Point(0,0),?new?Point(0,10));
????shapeImp.drawLine(new?Point(0,10),?new?Point(10,10));
????shapeImp.drawLine(new?Point(10,0),?new?Point(10,10));
??}
}




















?
類Client,橋接模式的客戶
?
package?qinysong.pattern.bridge;

import?qinysong.pattern.bridge.abstraction.Shape;
import?qinysong.pattern.bridge.abstraction.Square;
import?qinysong.pattern.bridge.abstraction.Triangle;


public?class?Client?...{


??public?static?void?main(String[]?args)?...{
????System.out.println("Client.main?begin?..........");
????Shape?shape?=?new?Square();
????shape.drawShape();
????Shape?shape2?=?new?Triangle();
????shape2.drawShape();

????System.out.println("Client.main?end???..........");
??}
}






















?
類ShapeImpFactory,工廠類,供抽象部分調用,分離實現類的創建過程
?
package?qinysong.pattern.bridge;

import?qinysong.pattern.bridge.implement.ShapeImp;
import?qinysong.pattern.bridge.implement.ShapeImpWin;


public?class?ShapeImpFactory?...{

??public?static?ShapeImp?getShapeImp()...{
????return?new?ShapeImpWin();
??}
}














posted on 2010-01-17 20:39 飛熊 閱讀(237) 評論(0) 編輯 收藏 所屬分類: java設計模式