橋接模式是將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。它是一種對(duì)象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interfce)模式。
概述在軟件系統(tǒng)中,某些類型由于自身的邏輯,它具有兩個(gè)或多個(gè)維度的變化,那么如何應(yīng)對(duì)這種“多維度的變化”?如何利用面向?qū)ο蟮募夹g(shù)來(lái)使得該類型能夠輕松的沿著多個(gè)方向進(jìn)行變化,而又不引入額外的復(fù)雜度?這就要使用Bridge模式。1
意圖【GOF95】在提出橋梁模式的時(shí)候指出,橋梁模式的用意是"將抽象化(Abstraction)與實(shí)現(xiàn)化(Implementation)脫耦,使得二者可以獨(dú)立地變化"。這句話有三個(gè)關(guān)鍵詞,也就是抽象化、實(shí)現(xiàn)化和脫耦。
抽象化存在于多個(gè)實(shí)體中的共同的概念性聯(lián)系,就是抽象化。作為一個(gè)過(guò)程,抽象化就是忽略一些信息,從而把不同的實(shí)體當(dāng)做同樣的實(shí)體對(duì)待。
實(shí)現(xiàn)化抽象化給出的具體實(shí)現(xiàn),就是實(shí)現(xiàn)化。
脫耦所謂耦合,就是兩個(gè)實(shí)體的行為的某種強(qiáng)關(guān)聯(lián)。而將它們的強(qiáng)關(guān)聯(lián)去掉,就是耦合的解脫,或稱脫耦。在這里,脫耦是指將抽象化和實(shí)現(xiàn)化之間的耦合解脫開(kāi),或者說(shuō)是將它們之間的強(qiáng)關(guān)聯(lián)改換成弱關(guān)聯(lián)。
將兩個(gè)角色之間的繼承關(guān)系改為聚合關(guān)系,就是將它們之間的強(qiáng)關(guān)聯(lián)改換成為弱關(guān)聯(lián)。因此,橋梁模式中的所謂脫耦,就是指在一個(gè)軟件系統(tǒng)的抽象化和實(shí)現(xiàn)化之間使用組合/聚合關(guān)系而不是繼承關(guān)系,從而使兩者可以相對(duì)獨(dú)立地變化。這就是橋梁模式的用意。2
結(jié)構(gòu)可以看出,這個(gè)系統(tǒng)含有兩個(gè)等級(jí)結(jié)構(gòu),也就是:
由抽象化角色和修正抽象化角色組成的抽象化等級(jí)結(jié)構(gòu)。
由實(shí)現(xiàn)化角色和兩個(gè)具體實(shí)現(xiàn)化角色所組成的實(shí)現(xiàn)化等級(jí)結(jié)構(gòu)。
橋梁模式所涉及的角色有:
抽象化(Abstraction)角色:抽象化給出的定義,并保存一個(gè)對(duì)實(shí)現(xiàn)化對(duì)象的引用。
修正抽象化(Refined Abstraction)角色:擴(kuò)展抽象化角色,改變和修正父類對(duì)抽象化的定義。
實(shí)現(xiàn)化(Implementor)角色:這個(gè)角色給出實(shí)現(xiàn)化角色的接口,但不給出具體的實(shí)現(xiàn)。必須指出的是,這個(gè)接口不一定和抽象化角色的接口定義相同,實(shí)際上,這兩個(gè)接口可以非常不一樣。實(shí)現(xiàn)化角色應(yīng)當(dāng)只給出底層操作,而抽象化角色應(yīng)當(dāng)只給出基于底層操作的更高一層的操作。
具體實(shí)現(xiàn)化(Concrete Implementor)角色:這個(gè)角色給出實(shí)現(xiàn)化角色接口的具體實(shí)現(xiàn)。2
示例[編輯]下列各語(yǔ)言的代碼都用于寫(xiě)出兩個(gè)不同的圓的坐標(biāo)和半徑。
API1.circle at 1:2 7.5
API2.circle at 5:7 27.5
Java/** "Implementor" */interface DrawingAPI{ public void drawCircle(double x, double y, double radius);}/** "ConcreteImplementor" 1/2 */class DrawingAPI1 implements DrawingAPI{ public void drawCircle(double x, double y, double radius) { System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius); }}/** "ConcreteImplementor" 2/2 */class DrawingAPI2 implements DrawingAPI{ public void drawCircle(double x, double y, double radius) { System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius); }}/** "Abstraction" */interface Shape{ public void draw(); // low-level public void resizeByPercentage(double pct); // high-level}/** "Refined Abstraction" */class CircleShape implements Shape{ private double x, y, radius; private DrawingAPI drawingAPI; public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) { this.x = x; this.y = y; this.radius = radius; this.drawingAPI = drawingAPI; } // low-level i.e. Implementation specific public void draw() { drawingAPI.drawCircle(x, y, radius); } // high-level i.e. Abstraction specific public void resizeByPercentage(double pct) { radius *= pct; }}/** "Client" */class BridgePattern { public static void main(String[] args) { Shape[] shapes = new Shape[2]; shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1()); shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2()); for (Shape shape : shapes) { shape.resizeByPercentage(2.5); shape.draw(); } }}C#using System; /** "Implementor" */ interface IDrawingAPI { void DrawCircle(double x, double y, double radius); } /** "ConcreteImplementor" 1/2 */ class DrawingAPI1 : IDrawingAPI { public void DrawCircle(double x, double y, double radius) { System.Console.WriteLine("API1.circle at {0}:{1} radius {2}", x, y, radius); } } /** "ConcreteImplementor" 2/2 */ class DrawingAPI2 : IDrawingAPI { public void DrawCircle(double x, double y, double radius) { System.Console.WriteLine("API2.circle at {0}:{1} radius {2}", x, y, radius); } } /** "Abstraction" */ interface IShape { void Draw(); // low-level (i.e. Implementation-specific) void ResizeByPercentage(double pct); // high-level (i.e. Abstraction-specific) } /** "Refined Abstraction" */ class CircleShape : IShape { private double x, y, radius; private IDrawingAPI drawingAPI; public CircleShape(double x, double y, double radius, IDrawingAPI drawingAPI) { this.x = x; this.y = y; this.radius = radius; this.drawingAPI = drawingAPI; } // low-level (i.e. Implementation-specific) public void Draw() { drawingAPI.DrawCircle(x, y, radius); } // high-level (i.e. Abstraction-specific) public void ResizeByPercentage(double pct) { radius *= pct; } } /** "Client" */ class BridgePattern { public static void Main(string[] args) { IShape[] shapes = new IShape[2]; shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1()); shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2()); foreach (IShape shape in shapes) { shape.ResizeByPercentage(2.5); shape.Draw(); } } }本詞條內(nèi)容貢獻(xiàn)者為:
黃倫先 - 副教授 - 西南大學(xué)