2010年3月15日 星期一

Design Pattern : 09 Bridge

通常產生子類別,會有兩種型態
1.extends繼承:
以繼承方式來產生子類別的目的,是在子類別新增功能
屬於功能性的擴增
2.implement實作:
父類別只是一個抽象類別(abstract)或介面(interface)
實作後的子類別,與父類別的功能是相同的,但每個功能可以有不同的展現
屬於實作部分的擴增

如果在做程式設計,希望可以把實作與功能部分完全分離,
如範例中,Display屬於功能性父類別,DisplayImp屬於實作父類別
如果想要新增功能,就擴充在Display的子類別內
如果想要改變輸出型態,如輸出文字變輸出html,
則新增DisplayImp的子類別

Bridge Pattern就是在功能類別(Display)內放一個變數(impl)存放實作類別(DisplayImp)的實體
讓功能類別(Display)內的method都是在操作實作類別(DisplayImp)的功能
把分離的實作擴充與功能擴充部分串起來,就是Bridge Pattern
參與者
1.Display(功能父類別)
在Display功能父類別內,利用一個變數impl儲存實作類別的instance
所有在功能類別內的操作,內部真正都執行的都是impl在執行

public class Display {
    private DisplayImp impl;
    public Display(DisplayImp impl){
        this.impl=impl;
    }
    public void open(){
        impl.rawOpen();
    }
} 

2.abstract DisplayImp(實作的父類別)
實作父類別,定義了所要實作類別所需要的method名稱,再交由子類別去實作出來

public abstract class DisplayImp {
    public abstract void rawOpen();
    public abstract void rawPrint();
    public abstract void rawClose();
}

3.CountDisplay(擴充了功能父類別Display)
要新增加功能,就加在這功能擴充的子類別上

public class CountDisplay extends Display {
    public CountDisplay(DisplayImp impl){
        super(impl);
    }
    public void multiOutPut(int num){
    this.open();
    this.print();
    this.print();
    this.close();
    }
}

4.StringDisplayImp(真正實作可以執行的實作類別)

public class StringDisplayImp extends DisplayImp {
    private String string;
    public StringDisplayImp(String string){
        this.string=string;
    }
    public void rawOpen(){
        System.out.println("---Is Open-------");
    };
    .....
}

5.Main外部程式

Display d1=new Display(new StringDisplayImp("OZ D1"));
CountDisplay d2=new CountDisplay(new StringDisplayImp("OZ D2"));
d1.output();
d2.output();
d2.multiOutPut(3);//執行功能擴充後,新增的method



ps:
當以繼承方式產生子類別,子類別並不會繼承父類別的建構子
如果父類別建構子有接受參數執行項目
那在繼承後,子類別在建構子內,並須執行super(xx)

沒有留言: