橋接模式
橋接模式用一種很巧妙的方式處理繼承存在的問題,用抽象關聯取代了傳統的多層繼承,將類之間的靜態繼承關係轉換爲動態的對象組合關係,使得系統更加靈活,並易於擴展,同時有效地控制了系統中類的個數。
模式動機
設想如果要繪製矩形、圓形、橢圓、正方形,我們至少需要四個形狀類,如果繪製的圖形需要具有不同的顏色,如紅色、綠色、藍色等,此時至少有兩種設計方案:第一種是爲每一個行政都提供一套各種顏色的版本,這種方案使用的是多級繼承結構,如果有四種形狀,十二種顏色,則我們需要四十八個類。如果要增加新形狀則同時也要具備所有的顏色,增加新的顏色也要爲所有的形狀添加對應顏色的子類;第二種提供四個形狀類、十二種顏色類,根據實際對形狀和顏色進行組合,此時系統中的類是十六個。如需增加新的形狀或顏色,只需再增加一個新的形狀類或顏色類即可。
很明顯,對於有兩個變化維度(即兩個變化的原因)的系統,採用方案二可以使系統中類的個數更少,且系統擴展更爲方便。
模式定義
將抽象部分與它的實現部分分離,使它們都可以獨立地變化
模式結構
橋接模式包含如下幾個角色:
-
Abstraction(抽象類)
用於定義抽象類的接口,它一般是抽象類而不是接口,其中定義一個Implementor類型對象使其與implementor之間具有關聯關係,它可以包含抽象的業務方法,還可以包含具體的業務方法。
-
RefineAbstraction(擴充抽象類)
擴充由Abstraction定義的接口,通常情況下是具體類,實現在Abstraction中定義的抽象業務方法,在RefineAbstraction可以調用Implementor中定義的業務方法。
-
Implementor(實現類接口)
對一些基本操作進行了定義,而具體實現交給其子類。
-
ConcreteImplementorA(具體實現類)
實現Implementor接口並且具體實現它,在不同的ConcreteImplementor中提供基本操作的不同實現,在程序運行時ConcreteImplementor對象將替換其父類對象,提供給客戶具體的業務操作方法。
橋接模式實例之模擬毛筆
-
實例說明
現需提供大小兩種型號的畫筆,能繪製三種不同的顏色,只需五個類就能實現功能。
-
實例代碼及解釋
-
實現類接口Color
public interface Color { void bepaint(String penType, String name); }
-
具體實現類Red
public class Red implements Color { @Override public void bepaint(String penType, String name) { System.out.println(penType + "紅色的" + name); } }
-
具體實現類Green
public class Green implements Color { @Override public void bepaint(String penType, String name) { System.out.println(penType + "綠色的" + name); } }
-
具體實現類Blue
public class Blue implements Color { @Override public void bepaint(String penType, String name) { System.out.println(penType + "藍色的" + name); } }
-
抽象類Pen
public abstract class Pen { protected Color color; public void setColor(Color color) { this.color = color; } public abstract void draw(String name); }
-
擴充抽象類BigPen
public class BigPen extends Pen { @Override public void draw(String name) { String penType = "大號毛筆繪製"; this.color.bepaint(penType, name); } }
-
擴充抽象類SmallPen
public class SmallPen extends Pen { @Override public void draw(String name) { String penType = "小號毛筆繪製"; this.color.bepaint(penType, name); } }
-
XML操作工具
public class XMLUtilPen { public static Object getBean(String args) { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(new File("configPen.xml")); NodeList nodeList = document.getElementsByTagName("className"); Node classNode = null; if (args.equals("color")) { classNode = nodeList.item(0).getFirstChild(); } else if (args.equals("pen")) { classNode = nodeList.item(1).getFirstChild(); } String cName = classNode.getNodeValue(); Class c = Class.forName("com.bridgePattern." + cName); Object o = c.newInstance(); return o; } catch (Exception e) { e.printStackTrace(); return null; } } }
-
客戶端測試類Client
public class Client { public static void main(String[] args) { Color color = (Color) XMLUtilPen.getBean("color"); Pen pen = (Pen) XMLUtilPen.getBean("pen"); pen.setColor(color); pen.draw("桃花"); } }
-
結果分析
如果在配置文件將第一個節點中內容設置爲 Red,第一個節點中內容設置爲 BigPen,則輸出結果如下:
如果在配置文件將第一個節點中內容設置爲 Blue,第一個節點中內容設置爲 SmallPen,則輸出結果如下:
如果需要增加新的毛筆或顏色,只需增加對應的擴充抽象類或具體實現類即可。在使用橋接模式設計的系統中,無論是哪個維度的擴展,對原有代碼都無須修改,且更換具體類只需修改配置文件,橋接模式通過抽象方法耦合,使得系統具有良好的擴展能力。
-