JAVA設計模式之橋接模式

1. 什麼是橋接模式?

橋接模式(Bridge Pattern):將抽象部分與他的實現部分分離,使他們都可以獨自變化。橋接模式是一種對象結構型模式。


對於有兩個或多個變化維度(即多個變化的原因)時,將每個維度分離開並採用相互組合的方式可以減少類與類之間的耦合,同時有利於擴展,這種方式就是橋接模式。對於定義中的抽象與實現分離開可以理解爲將維度與維度分離開,使之單獨變化,互不影響。


維度,又稱維數,是數學中獨立參數的數目。在物理學和哲學的領域內,指獨立的時空座標的數目。此處指獨立變化的參數數目,獨立變化的原因。

 

爲了加深理解,舉個例子:

例如當需要繪製矩形、圓形、三角形、菱形四種形狀,且每種形狀又有紅、黃、藍、紫四種不同的顏色,如果採用多繼承的方式來實現的話,至少需要4*4=16個類(忽略抽象父類或接口),比如紅矩形、黃矩形、綠矩形...。如果採用橋接模式,將圖形和顏色分離開來,通過組合的方式實現的話,就只需要4+4=8個類(忽略抽象父類或接口),而且最重要的是對於圖形和顏色的擴展相當方便。當維度數量越多時,橋接模式的優勢越明顯。此處的圖形和顏色就是兩個變化的維度,當單獨分離開後就可以相互組合了。

2. 角色

 

圖片來源於網絡


公共抽象類(Abstraction):此類定義公共的抽象方法,且有一個Implementor的引用。Abstraction的子類需要完善父類的方法,並且可以調用Implementor的方法來擴展父類的功能。

抽象類具體實現類(RefinedAbstraction):是Abstraction的具體實現,完善並擴展Abstraction的方法。

實現類接口(Implementor):定義了一系列的抽象類的實現方法,需要由子類實現。此類可以是接口或抽象類。方法可以和抽象類不同。實現類的方法都是爲抽象類服務的。

具體實現類(ConcreteImplementor):具體的實現類。

 

注意:此處不太好理解,什麼實現類什麼抽象類,容易讓人蒙圈。此處可以這樣理解,Abstraction和Implementor就是兩個不同的維度(不同的變化原因),比如圖形和顏色。而RefinedAbstraction就是具體的圖形,比如矩形、圓形等;ConcreteImplementor就是具體的顏色,比如紅色、黃色等。

3. 優點

(1)將抽象與實現分離,可以複用代碼,對於多維度場景可以減少類個數。

(2)通過組合的方式可以使類與類之間解耦。提高了系統的可擴展性,任意一個維度進行擴展都不需要修改原有系統。

(3)橋接模式是多繼承場景的更好解決方案。

4. 缺點

(1)橋接模式的引入會增加系統的理解與設計難度。

(2)橋接模式要求正確識別出系統中兩個或多個獨立變化的維度,因此其使用範圍具有一定的侷限性。

5. 使用場景

(1)一個類存在兩個或多個獨立變化的維度,且這些維度都需要進行獨立的擴展時可以使用橋接模式。

(2)對於那些不希望使用繼承或因爲多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤爲適用。

6. 實例代碼

繪製正方形、圓形兩種形狀,且每種形狀又有紅黃綠三種不同的顏色。不同的形狀就是一種維度,不同的顏色又是另一種維度。

 

(1)公共抽象類:圖形

/**
 * 圖形公共抽象類
 * 具有顏色的引用和一個畫圖的默認抽象方法
 */
public abstract class Figure {
	//顏色引用,每個圖形都有一種顏色
	private Colour colour;
	
	public Figure(Colour colour) {
		this.colour=colour;
	}
	
	public void setColour(Colour colour) {
		this.colour = colour;
	}

	public Colour getColour() {
		return colour;
	}
	//繪畫圖形
	public abstract void drew();
}

 

(2)實現類公共接口:顏色

/**
 * 顏色接口
 */
public interface Colour {
    //給物體上色方法
    public void pigment();
}

 

(3)抽象類具體實現類

/**
 * 正方形
 */
public class Square extends Figure {

	public Square(Colour colour) {
		super(colour);
	}

	@Override
	public void drew() {
		System.out.print("正方形:");
		this.getColour().pigment();
	}
}

/**
 * 圓形
 */
public class Circle extends Figure {

	public Circle(Colour colour) {
		super(colour);
	}
	@Override
	public void drew() {
		System.out.print("圓形:");
		this.getColour().pigment();
	}
}

 

(4)具體實現類

public class Red implements Colour {

	@Override
	public void pigment() {
		System.out.println("紅色的");
	}

}

public class Green implements Colour {

	@Override
	public void pigment() {
		System.out.println("綠色的");
	}
}

public class Yellow implements Colour {

	@Override
	public void pigment() {
		System.out.println("黃色的");
	}
}

 

(5)測試

public class Client {

	public static void main(String[] args) {
		//創建顏色對象
		Colour red=new Red();
		Colour yellow=new Yellow();
		Colour green=new Green();
		//畫三種顏色的圓形
		Figure circle1=new Circle(red);
		circle1.drew();
		Figure circle2=new Circle(yellow);
		circle2.drew();
		Figure circle3=new Circle(green);
		circle3.drew();
		//畫三種顏色的正方形
		Figure square1=new Square(green);
		square1.drew();
		Figure square2=new Square(red);
		square2.drew();
		Figure square3=new Square(yellow);
		square3.drew();
	}
}

 

(6)測試結果

圓形:紅色的
圓形:黃色的
圓形:綠色的
正方形:綠色的
正方形:紅色的
正方形:黃色的


【四川樂山程序員聯盟,歡迎大家加羣相互交流學習5 7 1 8 1 4 7 4 3】

發佈了41 篇原創文章 · 獲贊 63 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章