日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
設(shè)計(jì)模式系列—橋接模式

本篇和大家一起來(lái)學(xué)習(xí)橋接模式相關(guān)內(nèi)容。

創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括紫金網(wǎng)站建設(shè)、紫金網(wǎng)站制作、紫金網(wǎng)頁(yè)制作以及紫金網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,紫金網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶(hù)以成都為中心已經(jīng)輻射到紫金省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶(hù)的支持與信任!

 模式定義
將抽象與實(shí)現(xiàn)分離,使它們可以獨(dú)立變化。它是用組合關(guān)系代替繼承關(guān)系來(lái)實(shí)現(xiàn),從而降低了抽象和實(shí)現(xiàn)這兩個(gè)可變維度的耦合度。

模式實(shí)現(xiàn)如下:

 
 
 
 
  1. package com.niuh.designpattern.bridge.v1; 
  2.  
  3. /** 
  4.  * 橋接模式 
  5.  */ 
  6. public class BridgePattern { 
  7.     public static void main(String[] args) { 
  8.  
  9.         Implementor imple=new ConcreteImplementorA(); 
  10.         Abstraction abs=new RefinedAbstraction(imple); 
  11.         abs.Operation(); 
  12.  
  13.     } 
  14.  
  15. //實(shí)現(xiàn)化角色 
  16. interface Implementor { 
  17.     void OperationImpl(); 
  18.  
  19. //具體實(shí)現(xiàn)化角色 
  20. class ConcreteImplementorA implements Implementor { 
  21.  
  22.     public void OperationImpl() { 
  23.         System.out.println("具體實(shí)現(xiàn)化(Concrete Implementor)角色被訪(fǎng)問(wèn)"); 
  24.     } 
  25.  
  26. //抽象化角色 
  27. abstract class Abstraction { 
  28.     protected Implementor imple; 
  29.  
  30.     protected Abstraction(Implementor imple) { 
  31.         this.imple = imple; 
  32.     } 
  33.  
  34.     public abstract void Operation(); 
  35.  
  36. //擴(kuò)展抽象化角色 
  37. class RefinedAbstraction extends Abstraction { 
  38.     protected RefinedAbstraction(Implementor imple) { 
  39.         super(imple); 
  40.     } 
  41.  
  42.     public void Operation() { 
  43.         System.out.println("擴(kuò)展抽象化(Refined Abstraction)角色被訪(fǎng)問(wèn)"); 
  44.         imple.OperationImpl(); 
  45.     } 

輸出結(jié)果如下:

 
 
 
 
  1. 擴(kuò)展抽象化(Refined Abstraction)角色被訪(fǎng)問(wèn) 
  2. 具體實(shí)現(xiàn)化(Concrete Implementor)角色被訪(fǎng)問(wèn) 

解決的問(wèn)題
在有多種可能會(huì)變化的情況下,用繼承會(huì)造成類(lèi)爆炸問(wèn)題,擴(kuò)展起來(lái)不靈活。

模式組成
可以將抽象化部分與實(shí)現(xiàn)化部分分開(kāi),取消二者的繼承關(guān)系,改用組合關(guān)系。

實(shí)例說(shuō)明
實(shí)例概況
某公司開(kāi)發(fā)了一個(gè)財(cái)務(wù)管理系統(tǒng),其中有個(gè)報(bào)表生成器的工具模塊,客戶(hù)可以指定任意一種報(bào)表類(lèi)型,如基本報(bào)表,往來(lái)報(bào)表,資金報(bào)表,資產(chǎn)報(bào)表等,并且可以指定不同 的報(bào)表樣式,如餅圖,柱狀圖等。系統(tǒng)設(shè)計(jì)人員針對(duì)這個(gè)報(bào)表生成器的結(jié)構(gòu)設(shè)計(jì)了如下圖所示的類(lèi)圖。

后來(lái)在客戶(hù)使用過(guò)程中,客戶(hù)又希望增加一個(gè)新的報(bào)表和新的線(xiàn)形圖,開(kāi)發(fā)人員這個(gè)時(shí)候發(fā)現(xiàn)維護(hù)起來(lái)非常麻煩,設(shè)計(jì)人員經(jīng)過(guò)仔細(xì)分析,發(fā)現(xiàn)存在嚴(yán)重的問(wèn)題,因?yàn)樾略黾右粋€(gè)報(bào)表或者圖,需要增加很多子類(lèi)。所以,系統(tǒng)分析師最終對(duì)這個(gè)模塊根據(jù)面向?qū)ο蟮脑O(shè)計(jì)原則對(duì)上面的方案進(jìn)行了重構(gòu),重構(gòu)后的圖如下所示。

在本重構(gòu)方案中,將報(bào)表和圖形設(shè)計(jì)成兩個(gè)繼承結(jié)構(gòu),兩者都可以獨(dú)立變化,編程的時(shí)候可以只針對(duì)抽象類(lèi)編碼,而在運(yùn)行的時(shí)候再將具體的圖形子類(lèi)對(duì)象注入到具體的 報(bào)表類(lèi)中。這樣的話(huà),系統(tǒng)就具有良好的可擴(kuò)展性和可維護(hù)性,并且滿(mǎn)足了面向?qū)ο笤O(shè)計(jì)原則的開(kāi)閉原則。

使用步驟
步驟1:定義實(shí)現(xiàn)化角色,報(bào)表接口

 
 
 
 
  1. interface IReport { 
  2.     void operationImpl(); 

步驟2:定義具體實(shí)現(xiàn)化角色(基本報(bào)表、往來(lái)報(bào)表、資金報(bào)表)

 
 
 
 
  1. class BasicReport implements IReport { 
  2.  
  3.     @Override 
  4.     public void operationImpl() { 
  5.         System.out.println("基本報(bào)表被訪(fǎng)問(wèn)."); 
  6.     } 
  7.  
  8. class IntercourseReport implements IReport { 
  9.  
  10.     @Override 
  11.     public void operationImpl() { 
  12.         System.out.println("往來(lái)報(bào)表被訪(fǎng)問(wèn)."); 
  13.     } 
  14.  
  15. class CapitalReport implements IReport { 
  16.  
  17.     @Override 
  18.     public void operationImpl() { 
  19.         System.out.println("資金報(bào)表被訪(fǎng)問(wèn)."); 
  20.     } 

步驟3:定義抽象化角色,圖形

 
 
 
 
  1. abstract class AbstractionGraph { 
  2.     protected IReport iReport; 
  3.  
  4.     public AbstractionGraph(IReport iReport) { 
  5.         this.iReport = iReport; 
  6.     } 
  7.  
  8.     abstract void operation(); 

步驟4:定義擴(kuò)展抽象化角色(柱狀圖、餅圖)

 
 
 
 
  1. class Barchart extends AbstractionGraph { 
  2.  
  3.     public Barchart(IReport iReport) { 
  4.         super(iReport); 
  5.     } 
  6.  
  7.     @Override 
  8.     void operation() { 
  9.         System.out.println("柱狀圖被訪(fǎng)問(wèn)."); 
  10.         iReport.operationImpl(); 
  11.     } 
  12.  
  13. class Piechart extends AbstractionGraph { 
  14.  
  15.     public Piechart(IReport iReport) { 
  16.         super(iReport); 
  17.     } 
  18.  
  19.     @Override 
  20.     void operation() { 
  21.         System.out.println("餅圖被訪(fǎng)問(wèn)."); 
  22.         iReport.operationImpl(); 
  23.     } 

步驟5:測(cè)試

 
 
 
 
  1. public class BridgePattern { 
  2.  
  3.     public static void main(String[] args) { 
  4.         //實(shí)現(xiàn)化和抽象化分離 
  5.  
  6.         // 基本報(bào)表 
  7.         IReport basicReport = new BasicReport(); 
  8.         // 往來(lái)報(bào)表 
  9.         IReport intercourseReport = new IntercourseReport(); 
  10.         // 資金報(bào)表 
  11.         IReport capitalReport = new CapitalReport(); 
  12.  
  13.         // 基本報(bào)表使用柱狀圖 
  14.         AbstractionGraph barchart = new Barchart(basicReport); 
  15.         barchart.operation(); 
  16.  
  17.         // 基本報(bào)表使用餅圖 
  18.         AbstractionGraph piechart = new Piechart(basicReport); 
  19.         piechart.operation(); 
  20.     } 
  21.  

輸出結(jié)果

  • 柱狀圖被訪(fǎng)問(wèn).
  • 基本報(bào)表被訪(fǎng)問(wèn).
  • 餅圖被訪(fǎng)問(wèn).
  • 基本報(bào)表被訪(fǎng)問(wèn).

優(yōu)點(diǎn)
橋接模式遵循了里氏替換原則和依賴(lài)倒置原則,最終實(shí)現(xiàn)了開(kāi)閉原則,對(duì)修改關(guān)閉,對(duì)擴(kuò)展開(kāi)放。這里將橋接模式的優(yōu)缺點(diǎn)總結(jié)如下。

橋接(Bridge)模式的優(yōu)點(diǎn):

  • 抽象與實(shí)現(xiàn)分離,擴(kuò)展能力強(qiáng)
  • 符合開(kāi)閉原則
  • 符合合成復(fù)用原則
  • 其實(shí)現(xiàn)細(xì)節(jié)對(duì)客戶(hù)透明

缺點(diǎn)
由于聚合關(guān)系建立在抽象層,要求開(kāi)發(fā)者針對(duì)抽象化進(jìn)行設(shè)計(jì)與編程,能正確地識(shí)別出系統(tǒng)中兩個(gè)獨(dú)立變化的維度,這增加了系統(tǒng)的理解與設(shè)計(jì)難度。

應(yīng)用場(chǎng)景
當(dāng)一個(gè)類(lèi)內(nèi)部具備兩種或多種變化維度時(shí),使用橋接模式可以解耦這些變化的維度,使高層代碼架構(gòu)穩(wěn)定。

橋接模式通常適用于以下場(chǎng)景:

  1. 當(dāng)一個(gè)類(lèi)存在兩個(gè)獨(dú)立變化的維度,且這兩個(gè)維度都需要進(jìn)行擴(kuò)展時(shí);
  2. 當(dāng)一個(gè)系統(tǒng)不希望使用繼承或因?yàn)槎鄬哟卫^承導(dǎo)致系統(tǒng)類(lèi)的個(gè)數(shù)急劇增加時(shí);
  3. 當(dāng)一個(gè)系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性時(shí)。

橋接模式的一個(gè)常見(jiàn)使用場(chǎng)景就是替換繼承。我們知道,繼承擁有很多優(yōu)點(diǎn),比如,抽象、封裝、多態(tài)等,父類(lèi)封裝共性,子類(lèi)實(shí)現(xiàn)特性。繼承可以很好的實(shí)現(xiàn)代碼復(fù)用(封裝)的功能,但這也是繼承的一大缺點(diǎn)。

因?yàn)楦割?lèi)擁有的方法,子類(lèi)也會(huì)繼承得到,無(wú)論子類(lèi)需不需要,這說(shuō)明繼承具備強(qiáng)侵入性(父類(lèi)代碼侵入子類(lèi)),同時(shí)會(huì)導(dǎo)致子類(lèi)臃腫。因此,在設(shè)計(jì)模式中,有一個(gè)原則為優(yōu)先使用組合/聚合,而不是繼承。

橋接模式模式的擴(kuò)展
在軟件開(kāi)發(fā)中,有時(shí)橋接(Bridge)模式可與適配器模式聯(lián)合使用。當(dāng)橋接(Bridge)模式的實(shí)現(xiàn)化角色的接口與現(xiàn)有類(lèi)的接口不一致時(shí),可以在二者中間定義一個(gè)適配器將二者連接起來(lái),其結(jié)構(gòu)圖如下:

源碼中的應(yīng)用

 
 
 
 
  1. JDBC驅(qū)動(dòng)程序 
  2. ...... 

DriverManager類(lèi)

DriverManager作為一個(gè)抽象化角色,聚合了實(shí)現(xiàn)化角色Connection,只不過(guò)與標(biāo)準(zhǔn)的橋梁模式不一樣的是,DriverManager類(lèi)下面沒(méi)有子類(lèi)。

 
 
 
 
  1. //  Worker method called by the public getConnection() methods. 
  2. private static Connection getConnection( 
  3.  String url, java.util.Properties info, Class caller) throws SQLException { 
  4.         /* 
  5.          * When callerCl is null, we should check the application's 
  6.          * (which is invoking this class indirectly) 
  7.          * classloader, so that the JDBC driver class outside rt.jar 
  8.          * can be loaded from here. 
  9.          */ 
  10.         ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; 
  11.         synchronized(DriverManager.class) { 
  12.             // synchronize loading of the correct classloader. 
  13.             if (callerCL == null) { 
  14.                 callerCL = Thread.currentThread().getContextClassLoader(); 
  15.             } 
  16.         } 
  17.  
  18.         if(url == null) { 
  19.             throw new SQLException("The url cannot be null", "08001"); 
  20.         } 
  21.  
  22.         println("DriverManager.getConnection(\"" + url + "\")"); 
  23.  
  24.         // Walk through the loaded registeredDrivers attempting to make a connection. 
  25.         // Remember the first exception that gets raised so we can reraise it. 
  26.         SQLException reason = null; 
  27.  
  28.         for(DriverInfo aDriver : registeredDrivers) { 
  29.             // If the caller does not have permission to load the driver then 
  30.             // skip it. 
  31.             if(isDriverAllowed(aDriver.driver, callerCL)) { 
  32.                 try { 
  33.                     println("    trying " + aDriver.driver.getClass().getName()); 
  34.                     Connection con = aDriver.driver.connect(url, info); 
  35.                     if (con != null) { 
  36.                         // Success! 
  37.                         println("getConnection returning " + aDriver.driver.getClass().getName()); 
  38.                         return (con); 
  39.                     } 
  40.                 } catch (SQLException ex) { 
  41.                     if (reason == null) { 
  42.                         reason = ex; 
  43.                     } 
  44.                 } 
  45.  
  46.             } else { 
  47.                 println("    skipping: " + aDriver.getClass().getName()); 
  48.             } 
  49.  
  50.         } 
  51.  
  52.         // if we got here nobody could connect. 
  53.         if (reason != null)    { 
  54.             println("getConnection failed: " + reason); 
  55.             throw reason; 
  56.         } 
  57.  
  58.         println("getConnection: no suitable driver found for "+ url); 
  59.         throw new SQLException("No suitable driver found for "+ url, "08001"); 

PS:以上代碼提交在 Github :

https://github.com/Niuh-Study/niuh-designpatterns.git


文章名稱(chēng):設(shè)計(jì)模式系列—橋接模式
當(dāng)前URL:http://www.5511xx.com/article/cogechd.html