擴充套件系統功能——裝飾模式(三)
12.3 完整解決方案
為了讓系統具有更好的靈活性和可擴充套件性,克服繼承複用所帶來的問題,Sunny公司開發人員使用裝飾模式來重構圖形介面構件庫的設計,其中部分類的基本結構如圖12-4所示:
圖12-4 圖形介面構件庫結構圖
在圖12-4中,Component充當抽象構件類,其子類Window、TextBox、ListBox充當具體構件類,Component類的另一個子類ComponentDecorator充當抽象裝飾類,ComponentDecorator的子類ScrollBarDecorator和BlackBorderDecorator充當具體裝飾類。完整程式碼如下所示:
//抽象介面構件類:抽象構件類,為了突出與模式相關的核心程式碼,對原有控制元件程式碼進行了大量的簡化 abstract class Component { public abstract void display(); } //窗體類:具體構件類 class Window extends Component { public void display() { System.out.println("顯示窗體!"); } } //文字框類:具體構件類 class TextBox extends Component { public void display() { System.out.println("顯示文字框!"); } } //列表框類:具體構件類 class ListBox extends Component { public void display() { System.out.println("顯示列表框!"); } } //構件裝飾類:抽象裝飾類 class ComponentDecorator extends Component { private Component component; // public ComponentDecorator(Component component) //注入抽象構件型別的物件 { this.component = component; } public void display() { component.display(); } } //滾動條裝飾類:具體裝飾類 class ScrollBarDecorator extends ComponentDecorator { public ScrollBarDecorator(Component component) { super(component); } public void display() { this.setScrollBar(); super.display(); } public void setScrollBar() { System.out.println("為構件增加滾動條!"); } } //黑色邊框裝飾類:具體裝飾類 class BlackBorderDecorator extends ComponentDecorator { public BlackBorderDecorator(Component component) { super(component); } public void display() { this.setBlackBorder(); super.display(); } public void setBlackBorder() { System.out.println("為構件增加黑色邊框!"); } } |
編寫如下客戶端測試程式碼:
class Client { public static void main(String args[]) { Component component,componentSB; //使用抽象構件定義 component = new Window(); //定義具體構件 componentSB = new ScrollBarDecorator(component); //定義裝飾後的構件 componentSB.display(); } } |
編譯並執行程式,輸出結果如下:
為構件增加滾動條! 顯示窗體! |
在客戶端程式碼中,我們先定義了一個Window型別的具體構件物件component,然後將component作為建構函式的引數注入到具體裝飾類ScrollBarDecorator中,得到一個裝飾之後物件componentSB,再呼叫componentSB的display()方法後將得到一個有滾動條的窗體。如果我們希望得到一個既有滾動條又有黑色邊框的窗體,不需要對原有類庫進行任何修改,只需將客戶端程式碼修改為如下所示:
class Client { public static void main(String args[]) { Component component,componentSB,componentBB; //全部使用抽象構件定義 component = new Window(); componentSB = new ScrollBarDecorator(component); componentBB = new BlackBorderDecorator(componentSB); //將裝飾了一次之後的物件繼續注入到另一個裝飾類中,進行第二次裝飾 componentBB.display(); } } |
編譯並執行程式,輸出結果如下:
為構件增加黑色邊框! 為構件增加滾動條! 顯示窗體! |
我們可以將裝飾了一次之後的componentSB物件注入另一個裝飾類BlackBorderDecorator中實現第二次裝飾,得到一個經過兩次裝飾的物件componentBB,再呼叫componentBB的display()方法即可得到一個既有滾動條又有黑色邊框的窗體。
如果需要在原有系統中增加一個新的具體構件類或者新的具體裝飾類,無須修改現有類庫程式碼,只需將它們分別作為抽象構件類或者抽象裝飾類的子類即可。與圖12-2所示的繼承結構相比,使用裝飾模式之後將大大減少了子類的個數,讓系統擴充套件起來更加方便,而且更容易維護,是取代繼承複用的有效方式之一。