一、簡介
橋接模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,假如一個(gè)類需要在多個(gè)維度擴(kuò)展,采用繼承方式會導(dǎo)致子類數(shù)量過多。這時(shí)候可以采用橋接模式,將各個(gè)變化部分分離,從而實(shí)現(xiàn)獨(dú)立變化互不干涉,但又在更高的抽象層實(shí)現(xiàn)組合以保證各子類能動態(tài)結(jié)合。
優(yōu)點(diǎn)在于降低了類與類之間的耦合,使得系統(tǒng)中類的個(gè)數(shù)更少,且系統(tǒng)擴(kuò)展更為方便。
缺點(diǎn)在于橋接模式的引入會增加系統(tǒng)的理解與設(shè)計(jì)難度。
橋接模式包含如下角色:
? Abstraction:?抽象類,除了定義了當(dāng)前維度的抽象以外,一般包含另一維度的實(shí)例(即實(shí)現(xiàn)類接口的引用),起橋梁作用,也就是可以使得抽象部分和實(shí)現(xiàn)部分的子類可以隨意組合(即兩維度的變化隨意組合)。
? RefinedAbstraction:?擴(kuò)充抽象類,繼承了Abstraction
? Implementor: ?實(shí)現(xiàn)類接口,定義了另一維度的抽象
? ConcreteImplementor:?具體實(shí)現(xiàn)類,定義了另一維度的各種具體變化的實(shí)現(xiàn)

二、使用場景
一個(gè)類需要在多維度擴(kuò)展,采用繼承方式會導(dǎo)致子類數(shù)量過多。這時(shí)候可以采用橋接模式,將抽象部分與實(shí)現(xiàn)部分分離,各部分可以獨(dú)立變化,降低了類與類之間的耦合,使得系統(tǒng)中類的個(gè)數(shù)更少,且系統(tǒng)擴(kuò)展更為方便。
也就是說將一個(gè)需要多維度變化的類拆分成抽象部分和實(shí)現(xiàn)部分,并且在抽象層對兩者做組合關(guān)聯(lián),用組合的方式來解決繼承的問題。舉個(gè)例子,如果一個(gè)類在兩個(gè)維度分別有m和n種變化,采用繼承的方式就需要擴(kuò)展出m*n個(gè)子類,且一個(gè)維度每增加一種變化就多出另一個(gè)維度變化總數(shù)的子類;如果將兩個(gè)維度拆分再組合,加起來也只有m+n個(gè)子類,且每個(gè)維度獨(dú)立擴(kuò)展,一個(gè)維度增加一種變化只需要增加1個(gè)子類。
三、舉例
/*
* 以小攤販賣的早餐為例,我們從兩個(gè)維度分析,主食材有面條和煎餅等,輔助食材有雞蛋和肉絲等
* 我們把主食材作為抽象部分,輔助食材作為實(shí)現(xiàn)部分
*/
public class 橋接模式 {
public static void main(String[] args) {
MajorFood food1=new Noodle1(new Meat());
System.out.println(food1.getFood()+",共花費(fèi):"+food1.getCost());
MajorFood food2=new Pancake(new Egg());
System.out.println(food2.getFood()+",共花費(fèi):"+food2.getCost());
}
}
//先看實(shí)現(xiàn)部分
//首先定義實(shí)現(xiàn)類接口,一個(gè)維度
interface MinorFood{
String getDesc();
float getPrice();
}
//定義具體的實(shí)現(xiàn)類-雞蛋
class Egg implements MinorFood{
@Override
public String getDesc() {
return "雞蛋";
}
@Override
public float getPrice() {
return 1;
}
}
//定義具體的實(shí)現(xiàn)類-肉絲
class Meat implements MinorFood{
@Override
public String getDesc() {
return "肉絲";
}
@Override
public float getPrice() {
return 1.5f;
}
}
//再看抽象部分,作用類似于橋接模式中的橋,將兩個(gè)維度連接在一起
//定義抽象類(另一個(gè)維度),類中包含一個(gè)實(shí)現(xiàn)部分接口的引用,這樣抽象部分和實(shí)現(xiàn)部分的子類可以隨意組合
abstract class MajorFood{
protected MinorFood minorFood;//實(shí)現(xiàn)部分實(shí)例
public MajorFood(MinorFood minorFood){//橋接模式的關(guān)鍵,組合實(shí)現(xiàn)和抽象
this.minorFood=minorFood;
}
public abstract String getFood();
public abstract float getCost();
}
//定義擴(kuò)充抽象類-煎餅
class Pancake extends MajorFood{
public Pancake(MinorFood minorFood){
super(minorFood);
}
public String getFood(){
return "恭喜,獲得一份煎餅+"+super.minorFood.getDesc();
}
public float getCost(){
return 6+super.minorFood.getPrice();
}
}
//定義擴(kuò)充抽象類-面條
class Noodle1 extends MajorFood{
public Noodle1(MinorFood minorFood){
super(minorFood);
}
public String getFood(){
return "恭喜,獲得一份煮面+"+super.minorFood.getDesc();
}
public float getCost(){
return 8+super.minorFood.getPrice();
}
}
結(jié)果
恭喜,獲得一份煮面+肉絲,共花費(fèi):9.5
恭喜,獲得一份煎餅+雞蛋,共花費(fèi):7.0