橋接模式(Bridage Pattern)
此模式難度等級為中級猾编,屬結(jié)構(gòu)型模式限府,提出者為Gang Of Four
橋接(Bridge)是用于把抽象化與實(shí)現(xiàn)化解耦懂拾,使得二者可以獨(dú)立變化碳锈。
它通過提供抽象化和實(shí)現(xiàn)化之間的橋接結(jié)構(gòu)书在,來實(shí)現(xiàn)二者的解耦。
意圖
將抽象部分與實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立的變化
主要解決:在有多種可能會(huì)變化的情況下,用繼承會(huì)造成類爆炸問題笋庄,擴(kuò)展起來不靈活效扫。
何時(shí)使用:實(shí)現(xiàn)系統(tǒng)可能有多個(gè)角度分類,每一種角度都可能變化直砂。
如何解決:把這種多角度分類分離出來菌仁,讓它們獨(dú)立變化,減少它們之間耦合静暂。
關(guān)鍵代碼:抽象類依賴實(shí)現(xiàn)類济丘。
解釋
現(xiàn)實(shí)世界中的例子
考慮到你有一件武器具有不同的魔法,假如允許你讓不同的武器與不同的魔法混合洽蛀。你會(huì)怎么做摹迷?一為每個(gè)不同的魔法功能創(chuàng)建多個(gè)武器副本,二你會(huì)根據(jù)需要為武器創(chuàng)建單獨(dú)的魔法并設(shè)置它郊供。橋接模式就是你的第二選擇
簡而言之
橋接模式是關(guān)于更喜歡組合而不是繼承峡碉。實(shí)現(xiàn)細(xì)節(jié)從一個(gè)層次結(jié)構(gòu)派生到另一個(gè)具有單獨(dú)層次結(jié)構(gòu)的對象
維基百科
橋接模式是軟件工程中使用的一種設(shè)計(jì)模式,旨在“將抽象與其實(shí)現(xiàn)分離驮审,以便兩者可以獨(dú)立變化”
程序示例
以上面翻譯中我們現(xiàn)實(shí)世界中的武器例子鲫寄。如下來建造武器Weapon和魔法Enchantment的組合結(jié)構(gòu)。
首先編寫武器組織結(jié)構(gòu)代碼:
public interface Weapon {
void wield();
void swing();
void unwield();
Enchantment getEnchantment();
}
public class Sword implements Weapon {
private final Enchantment enchantment;
public Sword(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
LOGGER.info("The sword is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
LOGGER.info("The sword is swinged.");
enchantment.apply();
}
@Override
public void unwield() {
LOGGER.info("The sword is unwielded.");
enchantment.onDeactivate();
}
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}
public class Hammer implements Weapon {
private final Enchantment enchantment;
public Hammer(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
LOGGER.info("The hammer is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
LOGGER.info("The hammer is swinged.");
enchantment.apply();
}
@Override
public void unwield() {
LOGGER.info("The hammer is unwielded.");
enchantment.onDeactivate();
}
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}
其次編寫分離的魔法組織結(jié)構(gòu)代碼:
public interface Enchantment {
void onActivate();
void apply();
void onDeactivate();
}
public class FlyingEnchantment implements Enchantment {
@Override
public void onActivate() {
LOGGER.info("The item begins to glow faintly.");
}
@Override
public void apply() {
LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand.");
}
@Override
public void onDeactivate() {
LOGGER.info("The item's glow fades.");
}
}
public class SoulEatingEnchantment implements Enchantment {
@Override
public void onActivate() {
LOGGER.info("The item spreads bloodlust.");
}
@Override
public void apply() {
LOGGER.info("The item eats the soul of enemies.");
}
@Override
public void onDeactivate() {
LOGGER.info("Bloodlust slowly disappears.");
}
}
最后上面兩個(gè)組織層次都起作用疯淫,自動(dòng)橋接:
Sword enchantedSword = new Sword(new SoulEatingEnchantment());
enchantedSword.wield();
enchantedSword.swing();
enchantedSword.unwield();
// The sword is wielded.
// The item spreads bloodlust.
// The sword is swinged.
// The item eats the soul of enemies.
// The sword is unwielded.
// Bloodlust slowly disappears.
Hammer hammer = new Hammer(new FlyingEnchantment());
hammer.wield();
hammer.swing();
hammer.unwield();
// The hammer is wielded.
// The item begins to glow faintly.
// The hammer is swinged.
// The item flies and strikes the enemies finally returning to owner's hand.
// The hammer is unwielded.
// The item's glow fades.
應(yīng)用場景
當(dāng)遇到如下情況時(shí)你應(yīng)該使用橋接模式:
你希望避免抽象與其實(shí)現(xiàn)之間的永久綁定地来。例如,在運(yùn)行時(shí)必須選擇或切換實(shí)現(xiàn)時(shí)熙掺,可能會(huì)出現(xiàn)這種情況
抽象和它們的實(shí)現(xiàn)都應(yīng)該通過子類化來擴(kuò)展未斑。在這種情況下,Bridge模式允許你組合不同的抽象和實(shí)現(xiàn)币绩,并獨(dú)立地?cái)U(kuò)展它們
一個(gè)類存在兩個(gè)獨(dú)立變化的維度颂碧,且這兩個(gè)維度都需要進(jìn)行擴(kuò)展。
抽象中的具體實(shí)現(xiàn)發(fā)生變化時(shí)不應(yīng)影響客戶端类浪;也就是說,客戶端他們的代碼不應(yīng)該被重新編譯
對于那些不希望使用繼承或因?yàn)槎鄬哟卫^承導(dǎo)致系統(tǒng)類的個(gè)數(shù)急劇增加的系統(tǒng)肌似,橋接模式尤為適用
你想在多個(gè)對象之間共享一個(gè)實(shí)現(xiàn)(也許使用引用計(jì)數(shù))费就,這個(gè)事實(shí)應(yīng)該對客戶端隱藏。一個(gè)簡單的例子是Coplien的String類川队,其中多個(gè)對象可以共享相同的String表示
寫在最后
對于一個(gè)類存在兩個(gè)獨(dú)立變化的維度力细,使用橋接模式是再適合不過了。
將抽象和實(shí)現(xiàn)放在兩個(gè)不同的類層次中固额,使它們可以獨(dú)立地變化眠蚂。——《Head First 設(shè)計(jì)模式》
將類的功能層次結(jié)構(gòu)和實(shí)現(xiàn)層次結(jié)構(gòu)相分離斗躏,使二者能夠獨(dú)立地變化逝慧,并在兩者之間搭建橋梁,實(shí)現(xiàn)橋接〉殉迹—— 《圖解設(shè)計(jì)模式》
類的功能層次結(jié)構(gòu):父類具有基本功能云稚,在子類中增加新的功能;
類的實(shí)現(xiàn)層次結(jié)構(gòu):父類通過聲明抽象方法來定義接口沈堡,子類通過實(shí)現(xiàn)具體方法來實(shí)現(xiàn)接口静陈;
橋接模式中有四個(gè)角色:
抽象化角色:使用實(shí)現(xiàn)者角色提供的接口來定義基本功能接口。
持有實(shí)現(xiàn)者角色诞丽,并在功能接口中委托給它鲸拥,起到搭建橋梁的作用;
注意僧免,抽象化角色并不是指它就是一個(gè)抽象類刑赶,而是指抽象了實(shí)現(xiàn)。
改善后的抽象化角色:作為抽象化角色的子類猬膨,增加新的功能角撞,也就是增加新的接口(方法);與其構(gòu)成類的功能層次結(jié)構(gòu)勃痴;
實(shí)現(xiàn)者角色:提供了用于抽象化角色的接口谒所;它是一個(gè)抽象類或者接口。
具體的實(shí)現(xiàn)者角色:作為實(shí)現(xiàn)者角色的子類沛申,通過實(shí)現(xiàn)具體方法來實(shí)現(xiàn)接口劣领;與其構(gòu)成類的實(shí)現(xiàn)層次結(jié)構(gòu)。
最后铁材,如果抽象和實(shí)現(xiàn)兩者做不到獨(dú)立地變化尖淘,就不算橋接模式。
下一篇文章我們將學(xué)習(xí)結(jié)構(gòu)性模式中的過濾器模式(Filter Pattern)
碼字不易著觉,各位看官如果喜歡的話村生,請給點(diǎn)個(gè)喜歡 ??,關(guān)注下我饼丘,我將努力持續(xù)不斷的為大家更新