閱讀915 返回首頁    go 技術社區[雲棲]


Design Pattern: Decorator 模式

  學習是分享和合作式的!

轉載請注明出處:https://blog.csdn.net/wdzxl198/article/details/9417131

文章摘自: https://www.riabook.cn/doc/designpattern/

在Java Swing中的JTextArea元件預設並沒有卷軸,因為設計人員認為卷軸的功能並不是一定需要的,而決定讓程式人員可以動態選擇是否增加卷軸功能,卷 軸的功能是由JScrollPane元件提供,如果您要加入一個具有卷軸功能的JTextArea,您可以如下進行設計:

JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);

JScrollPane對JTextArea即是個容器,而它對JFrame來說又是個元件,可以如下這般將之加入JFrame中:

getContentPane().add(scrollPane);

像這樣動態的為JTextArea加入功能的方法,我們可以使用Decorator模式來組織結構,您可以動態的為一個物件加入一些功能(像是為 JTextArea加上卷軸),而又不用修改JTextArea的功能。對JTextArea來說,JScrollPane就好像是一個卷軸外框,直接套 在JTextArea上作裝飾,就好比您在照片上加上一個相框的意思。
先以上麵這個例子來說明Decorator模式的一個實例:

Decorator

如上圖所示的,無論是TextView或是Decorator類別,它們都是VisualComponent的一個子類,也就是說它們都是一個可視元件, 而Decorator類又聚合了VisualComponent,所以又可以當作TextView容器,ScrollDecorator類別實作了 Decorator類,它可能是這樣設計的:

public abstract class Decorator extends VisualComponent {
    protected VisualComponent component;
    public Decorator(VisualComponent component) {
        this.component = component;
    }
    public void draw() {
        component.draw();
    }
}
public class ScrollDecorator extends Decorator {
    public ScrollDecorator(VisualComponent component) {
        super(component);
    }
    public void draw() {
        super.draw();
        scrollTo();
    }
    public void scrollTo() {
        // ....
    }
}

要將新功能套用至TextView上,可以這樣設計:

ScrollDecorator scrollDecorator =
                    new ScrollDecorator(new TextView());

super.draw()會先唿叫component也就是TextView物件的draw()方法先繪製TextView,然後再進行 ScrollPanel的scrollTo(),也就是卷動的方法。在圖中也表示了一個BorderDecorator,它可能是這樣設計的:

public class BorderDecorator extends Decorator {
    public BorderDecorator(VisualComponent component) {
        super(component);
    }
    public void draw() {
        super.draw();
        drawBorder();
    }
    public void drawBorder() {
        // ....
    }
}

要將ScrollDecorator與BorderDecorator加至TextView上,我們可以這樣設計:

BorderDecorator borderDecorator =
         new BorderDecorator(
               new ScrollDecorator(new TextView()));

所以當BorderDecorator調用draw()方法時,它會先調用ScrollDecorator的draw()方法,而 ScrollDecorator的draw()方法又會先調用TextView的draw()方法,所以繪製的順序變成:

TextDraw.draw();
ScrollDecorator.scrollTo();
BorderDecorator.drawBorder();

下圖為物件之間的調用關係:

Decorator

Decorator模式的 UML 結構圖如下所示:

Decorator

在Gof的書中指出另一個範例,它設計一個Stream抽象類,而有一個StreamDecorator類,Stream的子類有處理記憶體串流的 MemoryStream與FileStream,有各種方法可以處理串流,也許隻是單純的處理字元,也許會進行壓縮,也許會進行字元轉換,最基本的處理 可能是處理字元,而字元壓縮被視為額外的功能,這個時候我們可以使用裝飾模式,在需要的時候為Stream物件加上必要的功能,事實上在java.io中 的許多輸入輸出物件,就是采取這樣的設計。

Edit by Atlas,

Time:21:03

最後更新:2017-04-03 16:48:42

  上一篇:go Oracle樹結構查詢——connect by語法詳解
  下一篇:go 產品經理(PM)常用原型圖設計工具