大話西遊裏有那麼一幕,牛魔王的妹妹使用移魂大法,使幾個人的靈魂交換。我們考慮一個問題,一個哲學問題,到底他們時靈魂發生了轉移,還是肉體發生了轉移。到底肉體是靈魂的載體,還是靈魂是肉體的產物。這部唯心主義了,不行不行,我可是社會唯物主義好青年,看我用橋接模式給你給他們連起來。(PS:爲了騙流量,博主起了這個名字,內容很有用)
橋接模式
橋接(Bridge)是用於把抽象化與實現化解耦,使得二者可以獨立變化。這種類型的設計模式屬於結構型模式,它通過提供抽象化和實現化之間的橋接結構,來實現二者的解耦。
這種模式涉及到一個作爲橋接的接口,使得實體類的功能獨立於接口實現類。這兩種類型的類可被結構化改變而互不影響。
橋接模式是一個非常有用的模式,也是比較複雜的一個模式。熟悉這個模式對於理解面向對象的設計原則,包括"開-閉"原則(OCP)以及組合/聚合複用原則(CARP)都很有幫助。理解好這兩個原則,有助於
形成正確的設計思想和培養良好的設計風格。
核心思想:以聚合代替原本的繼承關係,重構代碼結構實現松耦合(Coupling),二是高內聚(Cohesion)。
面向對象系統追求的目標就是儘可能地提高系統模塊內部的內聚(Cohesion)儘可能降低模塊間的耦合(Coupling)。然而這也是面向對象設計過程中最難把握的部分
優點:
- 抽象和實現的分離。
- 優秀的擴展能力。
- 實現細節對客戶透明。
缺點:
橋接模式的引入會增加系統的理解與設計難度,由於聚合關聯關係建立在抽象層,要求開發者針對抽象進行設計與編程。
適用場景:
- 如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態的繼承聯繫,通過橋接模式可以使它們在抽象層建立一個關聯關係。
- 對於那些不希望使用繼承或因爲多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤爲適用
- 一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。
實現:
我們用一個示例來形象的說明什麼事橋接 模式,但是這個例子不具有開發意義,只是爲了講清楚實現。
如果我們想實現PC系統和軟件的關係的軟件架構該如何實現。
(再次說明,只是爲了舉例,評論區總有擡槓的😂)
第一種方式:
感覺很良好,採用繼承方式。但是如果再增加一個Mac操作系統該怎麼辦?
看完可能會說,沒啥啊,不就多了幾個類,複製粘貼一下不就好了。
真的是這樣嗎?
- 開發時,複製粘貼絕不是一件好事,這個我們之前就說過。
- 如果說Kubuntu或者說CentOS和Unix等系統都要放到這裏呢,粘貼真的夠用嗎?
所以當二級分類一多,這裏軟件架構就不是那麼合理了!
第二種方式:
我這麼聰明我肯定有辦法啊!看我怎麼做!
你看,我這麼一重構,這不就完事了,我加個MAC,再來十個系統我也不怕!
結果老闆說,軟件不應該還有通訊軟件,音樂軟件,視頻軟件…
我暈!
又變得跟第一種一樣,每一種都是拖家帶口的生成!
第三種方式
所以我們要是用橋接模式,請看:
順勢我們給出橋接UML圖
具體代碼:
Implementor :
package 橋接模式;
public abstract class Implementor {
public abstract void Operaction();
}
ConcreteImplementorA
package 橋接模式;
public class ConcreteImplementorA extends Implementor {
@Override
public void Operaction() {
System.out.println("我是A的具體方法");
}
}
ConcreteImplementorB
package 橋接模式;
public class ConcreteImplementorB extends Implementor {
@Override
public void Operaction() {
System.out.println("我是B的具體方法");
}
}
Abstraction
package 橋接模式;
public class Abstraction {
protected Implementor im;
public void setIm(Implementor im) {
this.im = im;
}
void operaction() {
im.Operaction();
}
}
RefindAbstraction
package 橋接模式;
public class RefindAbstraction extends Abstraction {
public void Operaction() {
im.Operaction();
}
}
Client
package 橋接模式;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Abstraction ab=new RefindAbstraction();
ab.setIm(new ConcreteImplementorA());
ab.operaction();
ab.setIm(new ConcreteImplementorB());
ab.operaction();
}
}