디자인 패턴 ~Decorator~

1. 소개



GoF의 디자인 패턴에서 Decorator 패턴을 정리합니다.

2. Decorator 패턴이란?


  • Decorator라는 영어 단어는 장식(Decorate)하는 의미입니다.
  • Decorator 패턴은 객체에 점점 장식 (장식)하는 방법입니다.
  • 스폰지 케이크에 대해 크림, 초콜릿, 딸기 등으로 장식할 수 있도록 객체도 기능을 하나하나 씌워 장식해 가는 이미지가 됩니다.
  • GoF 디자인 패턴은 생성과 관련된 디자인 패턴으로 분류됩니다.

  • 3. 샘플 클래스 다이어그램





    4. 샘플 프로그램



    입력한 문자열에 테두리 등의 장식을 하는 프로그램입니다.

    4-1. Display 클래스



    캐릭터 라인 표시용의 추상 클래스입니다.

    Display.java
    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));
            }
        }
    }
    

    4-2. StringDisplay 클래스



    1행만으로 이루어지는 캐릭터 라인 표시용의 클래스입니다.

    StringDisplay.java
    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) {
            return (row == 0) ? string : null;
        }
    }
    

    4-3. Border 클래스



    장식 테두리를 나타내는 추상 클래스입니다.

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

    4-4. SideBorder 클래스



    좌우에 장식 테두리를 붙이는 클래스입니다.

    SideBorder.java
    public class SideBorder extends Border {
    
        public SideBorder(Display display) {
            super(display);
        }
    
        public int getColumns() {
            // 文字数は中身の両側に飾り文字分を加えた数
            return 1 + display.getColumns() + 1;
        }
    
        public int getRows() {
            // 行数は中身の行数に同じ
            return display.getRows();
        }
    
        public String getRowText(int row) {
            return "*" + display.getRowText(row) + "*";
        }
    }
    

    4-5. FullBorder 클래스



    상하 좌우에 장식 테두리를 붙이는 클래스입니다.

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

    4-6. Main 클래스



    메인 처리를 실시하는 클래스입니다.

    Main.java
    public class Main {
    
        public static void main(String[] args) {
            Display b1 = new StringDisplay("Hello world");
            b1.show();
            System.out.println("");
    
            Display b2 = new SideBorder(b1);
            b2.show();
            System.out.println("");
    
            Display b3 = new FullBorder(b2);
            b3.show();
            System.out.println("");
    
            Display b4 =
                new FullBorder(
                    new SideBorder(
                        new FullBorder(
                            new StringDisplay("Hello japan"))));
            b4.show();
        }
    }
    

    4-7. 실행 결과


    Hello world
    
    *Hello world*
    
    +-------------+
    |*Hello world*|
    +-------------+
    
    +---------------+
    |*+-----------+*|
    |*|Hello japan|*|
    |*+-----------+*|
    +---------------+
    

    5. 장점



    Decorator 패턴에서는, 장식 테두리(Border)도 내용(StringDisplay)도 공통의 인터페이스를 가지고 있습니다. 인터페이스는 공통이지만, 포장하면 감을수록 기능이 추가되어 갑니다. 그 때, 감싸는 쪽을 수정할 필요는 없습니다. 감싸는 것을 변경하지 않고 기능을 추가할 수 있습니다.

    6. GitHub


  • htps : // 기주 b. 코 m / 이타나카 730 /

  • 7. 디자인 패턴 목록


  • GoF 디자인 패턴 요약

  • 8. 참고



    이번 기사 및 샘플 프로그램은 이하의 서적을 바탕으로 작성하였습니다.
  • Java 언어로 배우는 디자인 패턴 입문

  • 매우 이해하기 쉽고 공부가되었습니다. 감사합니다.
    디자인 패턴이나 샘플 프로그램에 대한 설명이 상세하게 쓰여져 있으므로, 꼭 서적의 분도 봐 주세요.

    좋은 웹페이지 즐겨찾기