GOF设计模式之桥接模式
一、引入
現(xiàn)需要提供能夠繪制4種不同顏色且筆畫粗細(xì)有大中小3種型號的畫筆。
方法一:蠟筆
我們需要準(zhǔn)備3*4=12支蠟筆,也就是說必須準(zhǔn)備12個(gè)具體的蠟筆類
方法二:毛筆
只需要準(zhǔn)備三種型號的毛筆,外加四個(gè)顏料盒,用3+4=7個(gè)類就可以實(shí)現(xiàn)12支蠟筆的功能
二、定義
橋接模式的定義:將抽象與實(shí)現(xiàn)分離,使它們可以獨(dú)立變化。它是用關(guān)聯(lián)關(guān)系代替繼承關(guān)系來實(shí)現(xiàn),從而降低了抽象和實(shí)現(xiàn)這兩個(gè)可變維度的耦合度。
三、實(shí)現(xiàn)
基礎(chǔ)實(shí)現(xiàn)
//實(shí)現(xiàn)化角色 interface Implementor {public void OperationImpl(); } //具體實(shí)現(xiàn)化角色 class ConcreteImplementorA implements Implementor {public void OperationImpl(){System.out.println("具體實(shí)現(xiàn)化(Concrete Implementor)角色被訪問" );} //抽象化角色 abstract class Abstraction {protected Implementor imple;protected Abstraction(Implementor imple){this.imple=imple;}public abstract void Operation(); } //擴(kuò)展抽象化角色 class RefinedAbstraction extends Abstraction {protected RefinedAbstraction(Implementor imple){super(imple);}public void Operation(){System.out.println("擴(kuò)展抽象化(Refined Abstraction)角色被訪問" );imple.OperationImpl();} } //測試類 public class BridgeTest {public static void main(String[] args){Implementor imple=new ConcreteImplementorA();Abstraction abs=new RefinedAbstraction(imple);abs.Operation();} } //測試結(jié)果 擴(kuò)展抽象化(Refined Abstraction)角色被訪問 具體實(shí)現(xiàn)化(Concrete Implementor)角色被訪問畫筆實(shí)現(xiàn)
四、優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
-
分離抽象接口及其實(shí)現(xiàn)部分。
-
橋接模式有時(shí)類似于多繼承方案,但是多繼承方案違背了類的單一職責(zé)原則(即一個(gè)類只有一個(gè)變化的原因),復(fù)用性比較差,而且多繼承結(jié)構(gòu)中類的個(gè)數(shù)非常龐大,橋接模式是比多繼承方案更好的解決方法。
-
橋接模式提高了系統(tǒng)的可擴(kuò)充性,在兩個(gè)變化維度中任意擴(kuò)展一個(gè)維度,都不需要修改原有系統(tǒng)。
-
實(shí)現(xiàn)細(xì)節(jié)對客戶透明。
缺點(diǎn):
-
橋接模式的引入會增加系統(tǒng)的理解與設(shè)計(jì)難度,由于聚合關(guān)聯(lián)關(guān)系建立在抽象層,要求開發(fā)者針對抽象進(jìn)行設(shè)計(jì)與編程。
-
橋接模式要求正確識別出系統(tǒng)中兩個(gè)獨(dú)立變化的維度,因此其使用范圍具有一定的局限性。
五、使用場景
-
如果一個(gè)系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個(gè)層次之間建立靜態(tài)的繼承聯(lián)系,通過橋接模式可以使它們在抽象層建立一個(gè)關(guān)聯(lián)關(guān)系。
-
對于那些不希望使用繼承或因?yàn)槎鄬哟卫^承導(dǎo)致系統(tǒng)類的個(gè)數(shù)急劇增加的系統(tǒng),橋接模式尤為適用。
-
一個(gè)類存在兩個(gè)獨(dú)立變化的維度,且這兩個(gè)維度都需要進(jìn)行擴(kuò)展。
六、典型應(yīng)用
JDBC
String sql = "具體要操作的sql語句"; // 1:裝載驅(qū)動 Class.forName("驅(qū)動的名字"); // 2:創(chuàng)建連接 Connection conn = DriverManager.getConnection("連接數(shù)據(jù)庫服務(wù)的URL", "用戶名","密碼"); // 3:創(chuàng)建statement或者是preparedStatement PreparedStatement pstmt = conn.prepareStatement(sql); // 4:執(zhí)行sql,如果是查詢,再獲取ResultSet ResultSet rs = pstmt.executeQuery(sql); // 5:循環(huán)從ResultSet中把值取出來,封裝到數(shù)據(jù)對象中去 while (rs.next()) { // 取值示意,按名稱取值 String uuid = rs.getString("uuid"); // 取值示意,按索引取值 int age = rs.getInt(2); } //6:關(guān)閉 rs.close(); pstmt.close(); conn.close();我們寫的應(yīng)用程序,是面向JDBC的API在開發(fā),這些接口就相當(dāng)于橋接模式中的抽象部分的接口。JDBC的驅(qū)動程序?qū)崿F(xiàn)了JDBC的API,驅(qū)動程序就相當(dāng)于橋接模式中的具體實(shí)現(xiàn)部分。DriverManager來把它們橋接起來,從某個(gè)側(cè)面來看,DriverManager在這里起到了類似于簡單工廠的功能。
該例子詳情可見:https://www.jianshu.com/p/af6b1b27f638
介紹了廣義橋接模式和更多其他模式對比
七、對比
策略模式
相同點(diǎn):
- 在橋接模式中,Abstraction通過聚合的方式引用Implementor。
在策略模式中,Context也使用聚合的方式引用Startegy抽象接口。 - 在這兩種模式中,都存在一個(gè)對象使用聚合的方式引用另一個(gè)對象的抽象接口的情況,而且該抽象接口的實(shí)現(xiàn)可以有多種并且可以替換。可以說兩者在表象上都是調(diào)用者與被調(diào)用者之間的解耦,以及抽象接口與實(shí)現(xiàn)的分離。
不同點(diǎn):
-
在形式上,在橋接模式中不僅Implementor具有變化(ConcreateImplementior),而且Abstraction也可以發(fā)生變化(RefinedAbstraction),且兩者的變化是完全獨(dú)立的,RefinedAbstraction與ConcreateImplementior之間松散耦合,它們僅僅通過Abstraction與Implementor之間的關(guān)系聯(lián)系起來。而在策略模式中,并不考慮Context的變化,只有算法的可替代性。
-
在語意上,橋接模式強(qiáng)調(diào)Implementor接口僅提供基本操作,而Abstraction則基于這些基本操作定義更高層次的操作。而策略模式強(qiáng)調(diào)Strategy抽象接口的提供的是一種算法,一般是無狀態(tài)、無數(shù)據(jù)的,而Context則簡單調(diào)用這些算法完成其操作。
適配器模式
相同點(diǎn):
- 讓兩個(gè)東西配合工作,且和對象適配器模式一樣,都存在一個(gè)類調(diào)用另一個(gè)類。
不同點(diǎn):
- 假如A適配B(只針對對象的適配器),以及A橋接B
- 時(shí)機(jī):適配是在A,B都早已實(shí)現(xiàn)的情況下,而橋接反之,設(shè)計(jì)之初就要考慮
- 動機(jī):適配是A為了滿足B接口的需求封裝自己迎合B,橋接是AB兩個(gè)維度共同組合成一個(gè)實(shí)體。
裝飾器模式
相同點(diǎn):
- 使得兩者可以獨(dú)立變化??梢詼p少派生類的增長
不同點(diǎn):
- 裝飾是實(shí)現(xiàn)與實(shí)現(xiàn)之間的動態(tài)組合
- 橋接是抽象與實(shí)現(xiàn)的分離
總結(jié)
以上是生活随笔為你收集整理的GOF设计模式之桥接模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php实现飘窗,JS实现网站图片飘窗效果
- 下一篇: java指定sql生成xml_SQL S