--- tags: Structural Patterns --- # 裝飾模式 Decorator ## 架構圖 ![](https://i.imgur.com/nA7YnM6.png) **Component 參與者** 新增功能的核心參與者。在蛋糕的比喻說明中,相當於裝飾前的海綿蛋糕。Component 只規定海綿蛋糕的介面。例如 Display 類別。 **ConcreteComponent 參與者** 實作 Component 介面的具體海綿蛋糕。例如 StringDisplay 類別。 **Decorator (裝飾者) 參與者** 具有跟 Component 參與者相同的介面,另外還有 Decorator 要修飾的 Component。這個參與者是 "早就知道" 自己要去修飾的對象。例如 Border 類別。 **ConcreteDecorator 參與者** 具體的 Decorator 參與者,例如 SiderBorder 和 FullBorder 類別。 ## 範例 ``` java public abstract class Display { public abstract int getColumns(); // 取得橫向的字數 public abstract int getRows(); // 取得直向的行數 public abstract String getRowText(int row); // 取得第row個字串 public final void show() { // 列印所有內容 for (int i = 0; i < getRows(); i++) { System.out.println(getRowText(i)); } } } public abstract class Border extends Display { protected Display display; // 指裝飾外框裡面的內容,裝飾裡面也可能包含裝飾 protected Border(Display display) { // 產生物件個體時,以引數指定 "內容" this.display = display; } } public class FullBorder extends Border { public FullBorder(Display display) { super(display); } public int getColumns() { // 字數=內容字數+內容兩邊的裝飾字元 return 1 + display.getColumns() + 1; } public int getRows() { // 行數=內容行數+上下的裝飾字元 return 1 + display.getRows() + 1; } public String getRowText(int row) { // 指定該行的內容 if (row == 0) { // 外框頂端 return "+" + makeLine('-', display.getColumns()) + "+"; } else if (row == display.getRows() + 1) { // 外框底部 return "+" + makeLine('-', display.getColumns()) + "+"; } else { // 其他部分 return "|" + display.getRowText(row - 1) + "|"; } } private String makeLine(char ch, int count) { // 以字元ch,建立重複count次的連續字串 StringBuffer buf = new StringBuffer(); for (int i = 0; i < count; i++) { buf.append(ch); } return buf.toString(); } } public class SideBorder extends Border { private char borderChar; // 裝飾字元 public SideBorder(Display display, char ch) { // 以建構子指定Display和裝飾字元 super(display); this.borderChar = ch; } public int getColumns() { // 字數要再加上內容兩邊的裝飾字元 return 1 + display.getColumns() + 1; } public int getRows() { // 行數同內容的行數 return display.getRows(); } public String getRowText(int row) { // 指定該行的內容即為在內容之指定行的兩邊 // 加上裝飾字元 return borderChar + display.getRowText(row) + borderChar; } } //在這裡應用了 Template Method Pattern public class StringDisplay extends Display { private String string; // 列印的字串 public StringDisplay(String string) { // 以引數指定列印的字串 this.string = string; } public int getColumns() { // 字數 return string.getBytes().length; } public int getRows() { // 行數為1 return 1; } public String getRowText(int row) { // 僅在row為0時才傳回 if (row == 0) { return string; } else { return null; } } } public class Main { public static void main(String[] args) { Display b1 = new StringDisplay("Hello, world."); Display b2 = new SideBorder(b1, '#'); Display b3 = new FullBorder(b2); b1.show(); b2.show(); b3.show(); Display b4 = new SideBorder( new FullBorder( new FullBorder( new SideBorder( new FullBorder( new StringDisplay("您好。") ), '*' ) ) ), '/' ); b4.show(); } } ``` ## 寫法 宣告component的abstract ,再由abstract的decorator去繼承compoent 再由實作的decorator去自訂abstract decorator的fuc。 在上面範例中 是先宣告concretecomponent,再把這個變數傳入concretedecortator 就是把基本的功能丟進擴充的功能中。 人類扔進職位 new 職位decortator( new 人類() ) >[name=陳閔致]