Decorator 패턴

Jimin K·2023년 6월 7일
0

디자인 패턴

목록 보기
2/4

JAVA 언어로 배우는 디자인패턴 입문 책의 교재 및 예제 풀이를 정리해보려 한다.


Decorator 패턴은 중심이 되는 객체에 점점 장식을 더해가는 패턴이다.

교재는 예제로 특정 문자열의 길이만큼 장식문자 (+, -)를 붙여 출력하는 프로그램을 만든다.

총 사용하는 클래스는 6개로, Display, StringDisplay, Border, SideBorder, FullBorder, Main이다.

동작을 실행시키는 Main 클래스를 제외하고, 추상클래스인 Display 클래스를 부모로 두고, 이를 StringDisplayBorder가 상속받는 구조이다.

SideBorderFullBorderBorder 클래스를 상속받는 자식클래스이다.

Display 클래스에서는 세 개의 추상메소드를 선언하고 show() 메소드를 선언해 모든 행을 표시하도록 한다.
선언하는 추상메소드 세 개는 getColumns, getRows, getRowText 이다.

자세한 내용은 아래의 교재에서 제공하는 사이트를 참고해 예제를 확인하기 바란다.
https://www.youngin.com/reader/pds/pds.asp


문제 1 : 예제 프로그램에 추가하는 형태로 위아래 장식 문자가 붙는 UpDownBorder 클래스를 만들어 보라

만들어야 하는 결과는 아래와 같다.

Hello, world.
-------------
Hello, world.
-------------
*-------------*
*Hello, world.*
*-------------*
+-----------------+
|/////////////////|
||===============||
||*Hello, world.*||
||===============||
|/////////////////|
+-----------------+

이를 위해서 수정할 점은 문저 Main 클래스이다. 새로 생성할 클래스의 이름이 UpDownBorder이고, - 기호가 추가된 모양이므로, FullBorder를 제외한다.
사용하고 싶은 StringDisplay, UpDownDisplay, SidrBorder, FullBorder 에 따라서 아래와 같이 수정한다.


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("Hello, world."),
                                        '*'
                                    ),
                                    '='
                                ),
                                '|'
                            ),
                            '/'
                        )
                    );
        b4.show();
    }
}

그리고 새로 만든 UpDownDisplay는 FullBorder와 유사한 모양이되, 장식문자를 지칭하는 것을 생성한다.

    private char borderChar;  // 장식 문자 

    // 내용물이 될 Display와 장식 문자를 지정
    public UpDownBorder(Display display, char ch) {
        super(display);
        this.borderChar = ch;
    }
    
    ...
    
    

또한 getRowText부분을 수정해 row가 0일때 또는 row가 getRows() -1 일 때에 해당할 경우의 리턴값과 그렇지 않을 때의 리턴값을 수정해 준다.

...

@Override
    public String getRowText(int row) {
        if (row == 0 || row == getRows() -1) {                                             	// 상단 테두리
            return makeLine(borderChar, getColumns());
        } else {                                                    
            return display.getRowText(row - 1) ;
        }
    }
    
    ...

문제 2 : ConcreteComponent 역으로 여러 문자열을 표시하는 MultiStringDisplay 클래스를 만들어보라

완성해야하는 결과는 아래와 같다.

Hi!
Good morning.
Good night!
#Hi!          #
#Good morning.#
#Good night!  #
+-------------+
|Hi!          |
|Good morning.|
|Good night!  |
+-------------+

기존의 클래스에 새로은 클래스를 추가해주는데, 이름은 MultiStringDisplay이다.
출력결과를 보면 space와 데코레이견 기호를 같이 추가해주었다는 것을 알 수 있다.

이를 위해서 기존의 Main 클래스를 수정한다.


public class Main {
    public static void main(String[] args) {
        MultiStringDisplay md = new MultiStringDisplay();

        md.add("Hi!");
        md.add("Good mording.");
        md.add("Good night!");
        md.show();

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

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

그리고 MultiStringDisplay 클래스를 수정해주는데, 문자열을 저장하기 위해 리스트와 최대 문자 수를 저장할 변수를 새로 생성한다.

    private List<String> body = new ArrayList<>();

    private int columns = 0;

각 문자열을 추가받아 최대 문자 수를 갱신하는 add 메소드를 생성하며, 기존의 FullBorder 클래스 처럼 getColumns, getRows, getRowText 를 추가해준다.



    @Override
    public int getColumns() {
        // 문자 수는 내용물 양쪽에 좌우 장식 문자만큼 더한 것
        return columns;
    }

    @Override
    public int getRows() {
        // 행수는 내용물의 행수에 상하 장식 문자만큼 더한 것
        return body.size();
    }

    @Override
    public String getRowText(int row) {
        return body.get(row);
    }

또한 표시 문자열 오른쪽 끝에 채울 공백을 필요에 따라서 늘려야 하므로 메소드 하나를 추가해준다. 이름은 updatePadding() 이다.

 public void updatePadding() {
        for (int row = 0; row < body.size(); row++) {
            String line = body.get(row);
            int padding = columns - line.length();
            if (padding > 0) {
                body.set(row, line + spaces(padding));
            }
        }
    }

그리고 공백을 만드는 함수를 space라고 하며 count를 인수로 가진다.


    private String spaces(int count) {
        StringBuilder spaces = new StringBuilder();
        for (int i = 0; i < count; i++) {
            spaces.append(" ");
        }
        return spaces.toString();
    }
profile
아둥바둥

0개의 댓글