[디자인패턴] Decorator 패턴

Decorator 패턴

Decorator 패턴

Decorator 패턴-예제

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();
    }
}

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 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 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;
    }
}