一天一個設計模式——Bridge橋接模式

1、概念準備設計模式

  在理解橋接模式以前,先要理解面向對象程序設計中的兩個概念:ide

  • 類的功能層次結構:假設如今有一個類Something,這個類有一些成員屬性和成員方法,可是現有的功能不能知足要求,所以咱們想擴展這個類,給這個類建立一個子類SomethingBetter來繼承它,並在子類中添加更多屬性和方法。像這樣不一樣的功能位於不一樣的類繼承結構中,就構成了類的功能層次結構。
  • 類的實現層次結構:回顧一下抽象類的做用,抽象類聲明抽象方法(定義了方法接口API),而後在繼承它的子類中實現相關方法。因爲咱們將方法定義和實現分離到了不一樣的類中,從而實現了類的高可替換性,並有了模板Template Method方法模式。雖然這裏也有父類和子類的繼承關係,可是這裏的繼承並非爲了增長新功能,而是爲了完成「定義——實現 分離」中的實現環節。這種層次結構就是類的實現層次接口。

2、模式說明測試

  若是類的設計都只有一層(程序中自定義的類不存在繼承關係),這時候類的功能層次結構和實現層次結構是混雜在一塊兒的,也很難擴展(沒法肯定應該繼承哪一個類來擴展功能,同一個方法若是想替換其實現也沒法作到)。所以須要按照上面說的,將類的功能層次和實現層次分開,爲了在分開後能繼續保持必定的聯繫,這時候就須要一個橋樑,將它們鏈接起來。(Bridge也有橋樑的意思,鏈接兩個事物)this

3、代碼示例spa

  在下面的橋接模式代碼示例中,着重關注哪些時功能層次,哪些是實現層次,兩者又是如何橋接起來的。設計

一、類的功能層次結構code

Display類:Display類的功能是抽象的,負責「顯示」一些東西,它位於功能層次結構的最上層。open、print、close這三個方法是Display類提供的接口,它們定義了顯示的步驟,這三個方法調用的是Display實現類的對象。對象

package com.designpattern.cn.bridgepattern;

public class Display {
    private DisplayImpl impl;
    public Display(DisplayImpl impl){
        this.impl = impl;
    }
    public void open(){
        impl.rawOpen();
    }
    public void print(){
        impl.rawPrint();
    }
    public void close(){
        impl.rawClose();
    }
    public final void display(){
        open();
        print();
        close();
    }
}
View Code

CountDisplay類:CountDisplay類在Display類的基礎上增長了一個新功能,具備「只顯示規定次數」的功能。所以,這屬於「類的功能層次範疇」。blog

package com.designpattern.cn.bridgepattern;

public class CountDisplay extends Display {
    public CountDisplay(DisplayImpl impl){
        super(impl);
    }
    public void multiDisplay(int times){
        open();
        for(int i=0; i < times; i++){
            print();
        }
        close();
    }
}
View Code

 

二、類的實現層次結構繼承

DisplayImpl類:位於「類的實現層次結構」的最上層。DisplayImpl是抽象類,聲明瞭rawOpen、rawPrint、rawClose三個抽象方法。

package com.designpattern.cn.bridgepattern;

public abstract class DisplayImpl {
    public abstract void rawOpen();
    public abstract void rawPrint();
    public abstract void rawClose();
}
View Code

 

StringDisplayImpl類:它是仙子字符串的類,但它並非直接顯示字符串,而是繼承了DisplayImpl類,做爲子類來使用rawOpen、rawPrint、rawClose三個方法顯示字符串。

package com.designpattern.cn.bridgepattern;

public class StringDisplayImpl extends DisplayImpl {
    private String string;
    private int width;
    public StringDisplayImpl(String string){
        this.string = string;
        this.width = string.getBytes().length;
    }
    @Override
    public void rawOpen(){
        printLine();
    }
    @Override
    public void rawPrint(){
        System.out.println("|" + string + "|");
    }
    @Override
    public void rawClose() {
        printLine();
    }

    private void printLine(){
        System.out.print("+");
        for(int i = 0; i < width; i++){
            System.out.println("-");
        }
        System.out.println("+");
    }
}
View Code

 

三、Main類測試結果

 

4、模式類圖

5、模式中的角色

  • Abstraction抽象化:類的功能層次的最上層,它使用Implementor角色的方法定義了基本功能,如上面的Display類。
  • RefinedAbstraction改善後的抽象化:增長了Abstraction的功能,如上面的CountDisplay類。
  • Implementor實現者:類的實現層次結構最上層,定義了用於實現Abstraction的角色的接口方法,如上面的DisplayImpl類。
  • ConcreteImplementor具體實現者:負責實現Implementor角色定義的接口方法,如上面的StringDisplayImpl類。

那麼,這其中的橋樑Bridge是什麼呢?對於示例程序,Display類和DisplayImpl是如何關聯的,從程序中看出,這裏的橋樑應該是impl字段。

6、相關的設計模式

  • 模板方法Template Method模式:模板方法模式就是使用了橋接模式中的類的實現層次結構。父類調用抽象方法,子類實現具體方法。
  • 抽象工廠Abstract Factory模式:可使用抽象工廠設計出更好的ConcreteImplementor類。
  • 適配器Adapter模式:橋接模式鏈接了類的結構層次和實現層次,適配器模式則將功能相似,可是接口不匹配的類結合在一塊兒。

7、擴展

  • 採用bridge橋接模式分離功能層次和實現層次,更有利於類的擴展,若是要增長功能,只需在功能層次這一側作修改,無需調整實現層次,而且全部的實現層次都能利用增長的功能。
  • 繼承是強關聯,委託是弱關聯。繼承能夠方便的獲得功能更強的類,可是一旦使用繼承,則在類之間造成了強關聯關係,若是想改變或者替換其中的一個類,就必須修改類的代碼。上面的例子中,使用了委託,只有當Display類的實例生成時,才做爲參數,與被傳入的類構成關聯關係(示例程序中,只有Main類生成Display類和CountDisplay類的實例時,纔將StringDisplayImpl類的實例做爲參數傳遞給Display類和CountDisplay類)。除了StringDisplayImpl類,咱們可使用任意一個ConcreteImplementor角色傳遞給Display類和CountDisplay類,就能很容易的改變實現(只需修改Main類,Display類和DisplayImpl無需任何修改)。
相關文章
相關標籤/搜索