原文地址 http://blog.csdn.net/qq_25806863/article/details/70048778
橋接模式也叫橋樑模式,和生活中一樣,橋樑就是用來連接河道兩岸的主要建築。橋接模式也是起着連接兩邊的作用,連接的兩邊就是抽象部分和實現部分,這就需要在程序設計的時候劃分好抽象部分和實現部分了。
定義
將抽象部分與實現部分分離,使他們都可以獨立地進行變化。
使用場景
- 一個類存在兩個獨立維度的變化,且兩個維度都需要進行拓展。
- 一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免兩個層次之間建立靜態的繼承聯繫,可以用橋接模式使他們在抽象層建立一個關聯關係。
- 不想使用繼承或使用繼承會導致生成一大堆類的時候。
UML
- Abstraction: 抽象部分,抽象部分保持對實現部分的引用,抽象部分的方法要調用實現部分的對象來實現。一般爲抽象類。
- RefinedAbstraction: 優化的抽象部分,一般是對抽象部分的方法進行完善和拓展,是抽象部分的具體實現
- Implementor:實現部分,可以是接口和抽象類,方法不一定要和抽象部分保持一致。一般情況下由實現部分提供基本的操作,而抽象部分定義基於這些操作的業務方法。
- ConcreteImplementorA,B: 具體的實現部分。
模板代碼:
實現部分的接口:
public interface Implementor{
void operationImpl();
}
具體的實現部分:
public class ConcreteImplementorA implements Implementor{
@Override
public void operationImpl() {
//具體的實現
}
}
public class ConcreteImplementor implements Implementor{
@Override
public void operationImpl() {
//具體的實現
}
}
抽象部分:
public abstract class Abstraction{
private Implementor mImplementor;
public Abstraction(Implementor mImplementor) {
this.mImplementor = mImplementor;
}
public void operation(){
//調用實現部分的具體方法
mImplementor.operationImpl();
}
}
優化的抽象部分:
public class RefinedAbstraction extends Abstraction{
public RefinedAbstraction(Implementor mImplementor) {
super(mImplementor);
}
//可以增加拓展其他方法,也可以重寫父類的方法,也能調用父類的方法
@Override
public void refinedperation() {
//對抽象的父類的方法進行拓展
}
}
簡單實現
拿書中舉得例子。這裏用橋接模式來建立兩個維度之間的聯繫。對咖啡來說,可以分爲兩個維度,杯子大小是一個維度,加不加糖又是一個維度。這兩個沒有誰是抽象部分誰是具體部分。就拿杯子大小作爲抽象部分來做一個簡單實現:
抽象的糖,相當於實現部分的接口:
public abstract class CoffeeSugar {
public abstract void makeSugar();
}
兩種實現部分的實現,加不加糖:
public class AddSugar extends CoffeeSugar {
@Override
public void makeSugar() {
System.out.println("加糖的");
}
}
public class NoSugar extends CoffeeSugar {
@Override
public void makeSugar() {
System.out.println("不加糖的");
}
}
杯子的抽象,相當於抽象部分,持有一個糖的引用:
public abstract class CoffeeCup {
protected CoffeeSugar coffeeSugar;
public CoffeeCup(CoffeeSugar coffeeSugar) {
this.coffeeSugar = coffeeSugar;
}
public void makeCup(){
coffeeSugar.makeSugar();
}
}
優化的抽象部分,有大小兩種杯子:
public class LargeCup extends CoffeeCup {
public LargeCup(CoffeeSugar coffeeSugar) {
super(coffeeSugar);
}
@Override
public void makeCup() {
System.out.println("大杯的");
super.makeCup();
}
}
public class SmallCup extends CoffeeCup {
public SmallCup(CoffeeSugar coffeeSugar) {
super(coffeeSugar);
}
@Override
public void makeCup() {
System.out.println("小杯的");
super.makeCup();
}
}
客戶端調用:
public class Client {
public static void main(String[] args) {
CoffeeSugar addSugar = new AddSugar();
CoffeeSugar noSugar = new NoSugar();
CoffeeCup coffee = new LargeCup(addSugar);
coffee.makeCup();
System.out.println("---");
coffee = new LargeCup(noSugar);
coffee.makeCup();
System.out.println("---");
coffee = new SmallCup(noSugar);
coffee.makeCup();
}
}
輸出:
這樣就把兩個維度連接到一起了。而且兩個維度是可以獨立拓展的。比如如果想加上箇中杯,或者來個多糖少糖等分類,只需要多實現幾個類就行了,然後由客戶端去調用。這樣就能在兩個維度上獨立的拓展。
再想加上第三個維度也是很簡單的,現在要加上年齡分類,有老年人喝的喝年輕人喝的,者又是一個維度。
這時可以把前面兩個已經連接在一起的看做是一個維度,讓新的去橋接者個已有的。
抽象的people,持有一個之前的橋接,把people和CoffeeCup連接起來:
ublic abstract class People {
protected CoffeeCup coffeeCup;
public People(CoffeeCup coffeeCup) {
this.coffeeCup = coffeeCup;
}
public abstract void age();
}
具體的年齡分類:
public class YoungPeople extends People {
public YoungPeople(CoffeeCup coffeeCup) {
super(coffeeCup);
}
@Override
public void age() {
System.out.println("年輕人喝的");
coffeeCup.makeCup();
}
}
public class OldPeople extends People {
public OldPeople(CoffeeCup coffeeCup) {
super(coffeeCup);
}
@Override
public void age() {
System.out.println("老年人喝的");
coffeeCup.makeCup();
}
}
然後客戶端只需要這樣
public class Client {
public static void main(String[] args) {
CoffeeSugar addSugar = new AddSugar();
CoffeeSugar noSugar = new NoSugar();
CoffeeCup coffee = new LargeCup(addSugar);
coffee.makeCup();
System.out.println("---");
coffee = new LargeCup(noSugar);
coffee.makeCup();
System.out.println("---");
coffee = new SmallCup(noSugar);
coffee.makeCup();
System.out.println("-----");
//再次橋接
People people = new OldPeople(coffee);
people.age();
}
}
輸出:
總結
橋接模式就是把系統分爲抽象部分和實現部分,而建立橋接的方式也很簡單。就是讓抽象部分持有實現部分的引用,可以通過這個引用調用實現部分的具體方法。
使用這個系統最重要的是把握系統的分離,分不好就失去了靈活的拓展性,因此不容易設計。
優點
- 分離成抽象部分和實現部分,並且兩部分都可以獨立的拓展,一個部分變化不會引起另一部分的變化,提高了系統的拓展性。
- 複用性強,避免了使用繼承產生大量繼承類的問題。
缺點
- 將系統分離爲抽象部分和實現部分,會增加系統的複雜度和設計難度。如果系統不能分離出兩個獨立的維度的話,就不適合使用這個模式。