# 데코레이터 (Decorater) 패턴
# 데코레이터 패턴이란 무엇인가요?
기본 기능에 추가할 수 있는 기능의 종류가 많은 경우에 각 추가기능을 Decorator 클래스로 정의한 후
필요한 Decorator 객체를 조합함으로써 추가기능의 조합을 설계하는 방식입니다.
쉽게 말하자면 기존 코드를 변경하지 않고, 부가 기능을 추가하는 패턴입니다.
- 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 [어제보다 오늘 더]