본문 바로가기
개발/디자인 패턴

[Java 언어로 배우는 디자인 패턴 입문] 동일시하기 12. Decorator

by hongdor 2021. 1. 11.
728x90

출처 : 책 - java 언어로 배우는 디자인 패턴 입문

 

12. Decorator - 장식과 내용물을 동일시하기

 

 

1. 목적

 

 - 케이크에 크림을 바르고, 초콜릿을 입혀나가는 것처럼 이전 클래스를 받아 기능을 점차 추가(장식)해 나간다.

 - 장점 : 내용물을 변경하지 않고 기능을 추가할 수 있다.

            장식의 종류가 다른 오브젝트를 유연하게 생성할 수 있다.

 - 단점 : 작은 클래스가 많아진다.

 

잘 설명되어 잇는 유튜브를 소개한다.

(2) 객체지향 디자인패턴 2 - YouTube

 

 

2. 예제

 

(1) Display - 추상 클래스

public abstract class Display {
    public abstract int getColumns();               
    public abstract int getRows();                  
    public abstract String getRowText(int row);    
    public void show() {                            
        for (int i = 0; i < getRows(); i++) {
            System.out.println(getRowText(i));
        }
    }
}

 

 

(2) StringDisplay - 1행만 표현하는 클래스. 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() {                         
        return 1;
    }
    public String getRowText(int row) {            
        if (row == 0) {
            return string;
        } else {
            return null;
        }
    }
}

 

 

(3) Border - Display 클래스를 감싸고, 상속의 기준이 되는 Border 클래스를 만들어준다.

                    메소드의 구현보다 Display 클래스를 감싸고 있는 '장식' 클래스라는 의미가 더 중요하다.

                    장식클래스들의 기준이 되는 부모 추상 클래스이다. 

                   ( StringDisplay는 Display 의 하위 클래스이므로 Display로 받을 수 있기에 Border가 또한 감쌀 수 있다 )

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

 

 

(4) SideBorder - 좌우 경계 기능(장식) 추가

public class SideBorder extends Border {
    private char borderChar;                        
    public SideBorder(Display display, char ch) {   
        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;
    }
}

 

 

(5) FullBorder - 상하좌우 경계 기능(장식) 추가.

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) {       
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < count; i++) {
            buf.append(ch);
        }
        return buf.toString();
    }
}

 

 

(6) Main

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

댓글