# 데코레이터 (Decorater) 패턴

# 데코레이터 패턴이란 무엇인가요?

기본 기능에 추가할 수 있는 기능의 종류가 많은 경우에 각 추가기능을 Decorator 클래스로 정의한 후 필요한 Decorator 객체를 조합함으로써 추가기능의 조합을 설계하는 방식입니다.
쉽게 말하자면 기존 코드를 변경하지 않고, 부가 기능을 추가하는 패턴입니다.

  • UML
    데코레이터uml

# 예시 코드

라떼를 만드는데 여러 추가옵션들이 선택되었다고 가정하자.

  • Component (ex.추상화된 라떼)
public abstract class Latte {
    public abstract void add();
}
  • ConcreteComponent (ex.구체적으로 만들 카페라떼)
public class CafeLatte extends Latte {
    @Override
    public void add() {
        System.out.println("카페라떼");
    }
}
  • Decorator (ex.라떼에 추가할 옵션의 추상화)
public abstract class AddOption extends Latte {
    private Latte addOptionLatte;
    public AddOption(Latte addOptionLatte) {
        this.addOptionLatte = addOptionLatte;
    }
    @Override
    public void add() {
        addOptionLatte.add();
    }
}
  • Concrete Decorator1, 2 (ex.라떼에 추가할 옵션의 구체적인 모습)
public class AddShot extends AddOption {    // 샷추가 옵션
    public AddShot(Latte addOptionLatte) {
        super(addOptionLatte);
    }
    @Override
    public void add() {
        super.add();
        addShot();
    }
    private void addShot() {
        System.out.println("샷추가");
    }
}

public class SizeUp extends AddOption { // 사이즈업 옵션
    public SizeUp(Latte addOptionLatte) {
        super(addOptionLatte);
    }
    @Override 
    public void add() {
        super.add();
        SizeUp();
    }
    private void SizeUp() {
        System.out.println("사이즈업");
    }
}
  • 클라이언트에서의 사용
public class Client {
    public static void main(String[] args) {
        Latte latte = new CofeLatte();
        latte.add();    // 기본 카페라떼
        // 카페라떼가 출력됨

        Latte latte2 = new SizeUp(new AddShot(new CofeLatte()));
        latte2.add();   // 모든 옵션이 추가된 카페라떼     
        // 카페라떼 샷추가 사이즈업이 출력됨
    }
}

# 데코레이터 패턴은 언제 사용하나요?

  • 기본 기능에 추가할 수 있는 부가 기능의 종류가 많고 조합이 다양할 때 사용하면 좋습니다.
  • 동적으로 부가기능을 추가해야 할 때 사용하면 좋습니다.

# 데코레이터 패턴의 장점은 무엇인가요?

  • 새로운 클래스를 만들지 않고 기존 기능을 조합할 수 있습니다.
  • 런타임에 동적으로 기능을 변경하는 것이 가능합니다.

# 데코레이터 패턴의 단점은 무엇인가요?

  • 데코레이터를 조합하는 코드가 복잡할 수 있습니다.

# 실제로 사용한 데코레이터를 사용한 예는 무엇인가요?

  • 자바의 ArrayList의 add() 메소드
  • 스프링의 BeanDefinitionDecorator, ServerHttpRequestDecorator, ServerHttpResponseDecorator

# 참고자료

출처: 정인상, 채홍석.JAVA 객체지향 디자인 패턴.서울:한빛미디어,2019.
출처: https://kingchan223.tistory.com/299?category=894627 [어제보다 오늘 더]