데코레이터 패턴이란?

디자인 패턴 중 하나로 객체의 덧붙임을 통해 기능 등을 동적으로 유연하게 확장할 수 있는 패턴이다.

예시

GUI에서 윈도우 창 하나를 나타내는 Window 라는 타입에 가로 스크롤, 새로 스크롤, 전체 화면 기능을 추가한다고 해보자.

데코레이터 패턴을 사용하지 않은 경우

public class Window {
    public void draw() {
        // draw window
    }

    public String getDescription() {
        return "simple window";
    }
}

public class WindowWithVerticalScrollBar extends Window {
    public WindowWithVerticalScrollBar () {
        super();
    }
    
    @Override
    public void draw() {
        super.draw();
        // draw window
    }
    
    @Override
    public String getDescription() {
        return super.getDescription() + ", including vertical scrollbars";
    }
}

public class WindowWithHorizonScrollBar extends Window {
    public WindowWithHorizonScrollBar () {
        super();
    }

    @Override
    public void draw() {
        super.draw();
        // draw window
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", including horizon scrollbars";
    }
}

위와 같이 새로운 기능을 구현하게 된다면 새로운 기능이 추가될 때마다 클래스의 종류가 기하급수적으로 늘어난다 지금 위의 3가지 기능을 추가한다면 가능한 모든 클래스를 다만드려면 $2^n$개의 클래스를 만들어야된다.

데코레이터 패턴을 사용한 경우

데코레이터 패턴의 기본적이 구조는 아래와 같다.

decorator-pattern

  • Component: 기본 기능과 추가 기능의 공통적인 책임을 명세하는 인터페이스
  • ConcreteComponent: 기본 기능을 구현한 클래스
  • Decorator: 추가 기능으로 가질 책임들의 추상 클래스
  • ConcreteDecorator: Decorator를 상속받아 추가 기능을 구현한 클래스
interface Window {
    void draw();
    String getDescription();
}

class SimpleWindow implements Window {

    @Override
    public void draw() {
        // draw window
    }

    @Override
    public String getDescription() {
        return "simple window";
    }
}

abstract class WindowDecorator implements Window {
    private Window decoratedWindow;

    public WindowDecorator (Window decoratedWindow) {
        this.decoratedWindow = decoratedWindow;
    }

    @Override
    public void draw() {
        decoratedWindow.draw();
    }

    @Override
    public String getDescription() {
        return decoratedWindow.getDescription();
    }
}

class VerticalScrollBarDecorator extends WindowDecorator {
    public VerticalScrollBarDecorator(Window decoratedWindow) {
        super(decoratedWindow);
    }

    @Override
    public void draw() {
        super.draw();
        // draw vertical scrolls
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", including vertical scrollbars";
    }
}

class HorizontalScrollBarDecorator extends WindowDecorator {
    public HorizontalScrollBarDecorator (Window decoratedWindow) {
        super(decoratedWindow);
    }

    public void draw() {
        drawHorizontalScrollBar();
        super.draw();
    }

    private void drawHorizontalScrollBar() {
        // draw the horizontal scrollbar
    }

    public String getDescription() {
        return super.getDescription() + ", including horizontal scrollbars";
    }
}

WindowComponent, SimpleWindowConcreteComponent, WindowDecoratorDecorator에 해당한다. 아래와 같은 방법으로 여러 기능을 추가하여 사용할 수 있다.

Window windowWithVerticalAndHorizontalScroll
	= new HorizontalScrollBarDecorator(
	new VerticalScrollBarDecorator(
		new SimpleWindow()));

System.out.println(windowWithVerticalAndHorizontalScroll.getDescription());

결과는 가장 먼저 생성된 SimpleWindow부터 시작하여 simple window, including vertical scrollbars, including horizontal scrollbars가 출력된다. 이런 식으로 생성자에 추가할 기능을 이어 붙여서 원하는 기능들만 조합한 객체를 생성할 수 있다.

참고 자료

https://gmlwjd9405.github.io/2018/07/09/decorator-pattern.html

https://gdtbgl93.tistory.com/9

https://ko.wikipedia.org/wiki/데코레이터_패턴

댓글남기기