JAVA

[디자인패턴] Decorator 패턴

gom1n 2022. 4. 28. 08:59

Decorator 패턴?

중심이 되는 객체에, 장식과 같은 부가적인 기능을 하나씩 입혀서 목적에 어울리는 객체로 만들고자 생겨난 패턴이다.

Decorator 패턴의 객체들은 장식을 할 수 있는 동시에, 장식이 될 수 있는 가능성이 있다. (장식자이면서, 장식의 대상이 된다.)

언뜻 보면 Composite패턴과 비슷할 정도로 재귀적인 구조를 가진다.

그러나 객체가 다른 객체에 포함될 수 있는 Composite 패턴과 달리, Decorator 패턴은 객체는 다른 객체에 의해 덧붙여진다는, 즉 기능추가가 된다는 점에서 다르다.

 

다이어그램

 

 

Decorator 패턴의 핵심 클래스 : Border.class

public abstract class Border extends Display {
	protected Display display; 
    protected Border(Display display) {
    	this.display = display;
    }
}

 

Decorator Pattern in Java API

 Java IO classes, like FileReaderBufferedReader, etc.

 


연습문제

12-1) 이 장의 프로그램에 추가하는 형태로 상하에 장식문자가 붙는 UpDownBorder 클래스를 만드십시오. UpDownBorder 클래스는 다음과 같이 사용한다고 가정합니다.

 

Main.class에서의 UpDownBorder 클래스 사용

public class Main {
    public static void main(String[] args) {
        Display b1 = new StringDisplay("Hello, world.");
        Display b2 = new UpDownBorder(b1, '-');
        Display b3 = new SideBorder(b2, '*');
        b1.show();
        b2.show();
        b3.show();
        Display b4 = 
                    new FullBorder(
                        new UpDownBorder(
                            new SideBorder(
                                new UpDownBorder(
                                    new SideBorder(
                                        new StringDisplay("안녕하세요."),
                                        '*'
                                    ),
                                    '='
                                ),
                                '|'
                            ),
                            '/'
                        )
                    );
        b4.show();
    }
}

 

 

답) UpDownBorder 클래스

public class UpDownBorder extends Border {
    private char borderChar;                       
    public UpDownBorder(Display display, char ch) {  
        super(display);
        this.borderChar = ch;
    }
    public int getColumns() {                  
        return display.getColumns();
    }
    public int getRows() {                    
        return 1 + display.getRows() + 1;
    }
    public String getRowText(int row) {         
        if (row == 0 || row == getRows() - 1) {
            return makeLine(borderChar, getColumns());
        } else {
            return display.getRowText(row - 1);
        }
    }
    private String makeLine(char ch, int count) {  
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < count; i++) {
            buf.append(ch);
        }
        return buf.toString();
    }
}

 

 

 

12-2) ConcreteComponent 역할로 복수의 문자열을 표시하는 MultiStringDisplay 클래스를 만드십시오. MultiStringDisplay는 다음과 같이 사용한다고 가정합니다. 

 

Main.class에서의 MultiStringDisplay 클래스 사용

public class Main {
    public static void main(String[] args) {
        MultiStringDisplay md = new MultiStringDisplay();
        md.add("좋은 아침입니다.");
        md.add("안녕하세요.");
        md.add("안녕히 주무세요. 내일 만나요.");
        md.show();

        Display d1 = new SideBorder(md, '#');
        d1.show();

        Display d2 = new FullBorder(md);
        d2.show();
    }
}

 

 

) MultiStringDisplay 클래스

import java.util.ArrayList;

public class MultiStringDisplay extends Display {
    private ArrayList body = new ArrayList();       
    private int columns = 0;                      
    public void add(String msg) {                 
        body.add(msg);
        updateColumn(msg);
    }
    public int getColumns() {                   
        return columns;
    }
    public int getRows() {                        
        return body.size();
    }
    public String getRowText(int row) {            
        return (String)body.get(row);
    }
    private void updateColumn(String msg) {      
        if (msg.getBytes().length > columns) {
            columns = msg.getBytes().length;
        }
        for (int row = 0; row < body.size(); row++) {
            int fills = columns - ((String)body.get(row)).getBytes().length;
            if (fills > 0) {
                body.set(row, body.get(row) + spaces(fills));
            }
        }
    }
    private String spaces(int count) {             
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < count; i++) {
            buf.append(' ');
        }
        return buf.toString();
    }
}