IT/JAVA
🧱 데코레이터 패턴 완전 정복 - 커피 주문 예제로 배우는 디자인 패턴
밥알이
2025. 6. 1. 22:18
디자인 패턴을 처음 배우는 사람도, 실무에서 적용해보고 싶은 개발자도 쉽게 이해할 수 있도록, 데코레이터 패턴을 현실적인 예제와 함께 설명드립니다.
✅ 1. 데코레이터 패턴이란?
데코레이터(Decorator) 패턴은
"기존 객체에 추가적인 기능을 런타임에 동적으로 부여할 수 있는 구조 패턴"
- 상속을 사용하지 않고 기능을 확장할 수 있어,
- 유연한 조합이 필요할 때 적합합니다.
🎨 2. 실생활 비유: 커피 주문 시스템
커피 = 기본 객체
추가 옵션 = 데코레이터
예를 들어, 커피를 주문할 때 다음과 같은 옵션을 붙일 수 있습니다.
- 기본 커피: 아메리카노
- 추가 옵션: 우유, 시럽, 휘핑 등
각 옵션은 기존 커피 객체를 감싸는 구조로, ‘싸듯이(decorate)’ 기능을 확장합니다.
📌 3. 언제 사용하나요?
상황 | 설명 |
---|---|
✔️ 기능 확장이 동적으로 필요할 때 | 런타임에 선택적으로 기능 조합 |
✔️ 상속보다 조합(Composition)이 더 적합할 때 | 계층 구조 대신 조립식 구조 사용 |
✔️ 기존 코드를 건드리지 않고 기능을 추가하고 싶을 때 | OCP 원칙 준수 가능 |
🎯 4. 예제 시나리오
Beverage
라는 커피 인터페이스가 있습니다.Americano
는 기본 커피입니다.Milk
,Vanilla
는 추가 옵션입니다.- 각 옵션은 기존 음료를 감싸며 기능을 더합니다.
🔧 5. 실무형 자바 예제
📁 1) 기본 컴포넌트 인터페이스
public interface Beverage {
String getDescription();
int getCost();
}
📁 2) 기본 커피 클래스
public class Americano implements Beverage {
@Override
public String getDescription() {
return "아메리카노";
}
@Override
public int getCost() {
return 2000;
}
}
📁 3) 추상 데코레이터
public abstract class BeverageDecorator implements Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
📁 4) 옵션 데코레이터 (우유, 바닐라)
public class Milk extends BeverageDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 우유";
}
@Override
public int getCost() {
return beverage.getCost() + 500;
}
}
public class Vanilla extends BeverageDecorator {
public Vanilla(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 바닐라";
}
@Override
public int getCost() {
return beverage.getCost() + 700;
}
}
📁 5) 사용 예제
public class Main {
public static void main(String[] args) {
Beverage coffee = new Americano(); // 기본 커피
coffee = new Milk(coffee); // 우유 추가
coffee = new Vanilla(coffee); // 바닐라 추가
System.out.println("주문: " + coffee.getDescription());
System.out.println("가격: " + coffee.getCost() + "원");
}
}
✅ 실행 결과
주문: 아메리카노, 우유, 바닐라
가격: 3200원
🧠 6. 구조 요약 (UML 개념)
[Beverage] <interface>
▲ ▲
[Americano] [BeverageDecorator]
▲
[Milk], [Vanilla], ...
💡 7. 실무 사용 사례
사례 | 설명 |
---|---|
🔗 Spring FilterChain | 필터 체인처럼 연결해 기능 확장 |
📦 BufferedInputStream | 스트림을 감싸며 기능 추가 |
🔍 Logger wrapper | 로그 객체에 기능 덧붙이기 |
🖼️ UI 컴포넌트 | 테두리, 그림자 등 시각 효과 확장 |
📈 8. 장점 vs 단점
✅ 장점
- 유연한 기능 확장: 상속 없이도 다양한 조합 가능
- OCP 원칙 준수: 기존 코드 수정 없이 기능 추가
- 런타임 조합 가능: 상황에 따라 유연한 객체 구성
⚠️ 단점
- 클래스 수 증가: 옵션마다 클래스가 필요
- 복잡한 구조: 중첩이 많아질 경우 디버깅 어려움
📝 9. 요약 정리
항목 | 설명 |
---|---|
🧱 이름 | 데코레이터(Decorator) 패턴 |
🎯 목적 | 기존 객체의 기능을 동적으로 확장 |
🧩 구조 | Component + Decorator |
🛠️ 실무 활용 | 스트림, 필터, 로깅, UI 효과 등 |
🧵 마무리 한 줄 요약
데코레이터 패턴은 “조합 가능한 기능 확장”을 가능하게 해주는 구조 패턴입니다.
상속보다 유연하고, 변경보다 확장을 추구하는 객체지향의 정수를 담고 있죠.