최종 보스

✅ Decorator Pattern란?
- Decorator Pattern(데코레이터 패턴)은 객체에 기능을 동적으로 추가할 수 있게 해주는 구조적 디자인 패턴
- 핵심은 상속이 아니라 객체를 감싸는(합성) 방식으로 기능을 확장
- 데코레이터 패턴은 기존 객체를 감싸서 새로운 기능을 추가할 수 있게 하는 패턴
✅ 언제 사용하나?
- 기존 코드를 건드리지 않고 기능을 확장하고 싶을 때
- 기능의 조합이 유동적이거나, 다양한 조합의 객체가 필요할 때
- 상속으로는 조합이 너무 많아져서 클래스 폭발 문제가 생길 때
✅ 구조
┌──────────────┐
│ Component │ ← 공통 인터페이스
└──────────────┘
▲
┌─────────┴─────────┐
│ │
ConcreteComponent Decorator (추상 클래스)
▲
┌────────────────┴──────────────┐
│ │
ConcreteDecoratorA ConcreteDecoratorB
✅ 자바 예제: 커피에 우유/시럽 추가하기
1.
Component
인터페이스public interface Coffee {
String getDescription();
int cost();
}
2.
ConcreteComponent
: 기본 커피public class BasicCoffee implements Coffee {
public String getDescription() {
return "기본 커피";
}
public int cost() {
return 3000;
}
}
3.
Decorator
: Coffee 인터페이스를 구현하고 원본을 참조public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
4.
ConcreteDecorator
: 실제 기능 확장public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
public String getDescription() {
return coffee.getDescription() + ", 우유 추가";
}
public int cost() {
return coffee.cost() + 500;
}
}
public class SyrupDecorator extends CoffeeDecorator {
public SyrupDecorator(Coffee coffee) {
super(coffee);
}
public String getDescription() {
return coffee.getDescription() + ", 시럽 추가";
}
public int cost() {
return coffee.cost() + 300;
}
}
✅ 사용 예
Coffee coffee = new BasicCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SyrupDecorator(coffee);
System.out.println(coffee.getDescription()); // 기본 커피, 우유 추가, 시럽 추가
System.out.println(coffee.cost()); // 3000 + 500 + 300 = 3800
✅ 장점
장점 | 설명 |
🎯 기존 코드를 수정하지 않고 기능 확장 가능 | Open-Closed Principle(OCP) 지킴 |
🔀 다양한 기능 조합이 가능 | 우유+시럽, 시럽+우유, 등 |
🧩 계층 구조 없이 기능을 조립 가능 | 상속보다 유연함 |
❌ 단점
단점 | 설명 |
🧠 중첩이 많아지면 디버깅 어려움 | 디버깅 시 구조 파악이 복잡할 수 있음 |
🧱 클래스 수 증가 | 데코레이터마다 별도 클래스 필요 |
✅ 실제 사용 예
실생활 예 | 설명 |
자바 IO 스트림 | BufferedInputStream(new FileInputStream(...)) |
Spring Security 필터 체인 | 필터를 데코레이터처럼 연결 |
로그 처리기 | 여러 데코레이터로 로그 포맷, 출력 대상 등을 조합 |
✅ 정리
항목 | 내용 |
목적 | 객체의 기능을 런타임에 동적으로 확장 |
방법 | 객체를 감싸는 방식(합성)으로 새로운 동작 추가 |
특징 | 원래 객체를 수정하지 않고 기능 추가 가능 |
예시 | 자바 IO, Spring 필터 체인 |
실습
Notifier
package ex06.notification;
public interface Notifier {
void send();
}
BasicNotifier
package ex06.notification;
// 책임: 알림 전송
public class BasicNotifier implements Notifier {
public void send() {
System.out.println("기본 알림");
}
}
EmailNotifier
package ex06.notification;
// 책임: 알림 전송
public class EmailNotifier implements Notifier {
private Notifier notifier; // has
// 기본 생성자
public EmailNotifier() {
}
// 의존성 주입
public EmailNotifier(Notifier notifier) {
this.notifier = notifier;
}
public void send() {
System.out.println("이메일 알림");
if (notifier != null) notifier.send(); // 의존하는 게 있으면 실행
}
}
SmsNotifier
package ex06.notification;
// 책임: 알림 전송
public class SmsNotifier implements Notifier {
private Notifier notifier; // has
// 기본 생성자
public SmsNotifier() {
}
// 의존성 주입
public SmsNotifier(Notifier notifier) {
this.notifier = notifier;
}
public void send() {
System.out.println("문자 알림");
if (notifier != null) notifier.send();
}
}
ClientNotification
package ex06;
import ex06.notification.Notifier;
public class ClientNotification {
public static void send(Notifier notifier) {
notifier.send();
}
}
App
package ex06;
import ex06.notification.BasicNotifier;
import ex06.notification.EmailNotifier;
import ex06.notification.SmsNotifier;
public class App {
public static void main(String[] args) {
// Notifier b1 = new BasicNotifier();
// b1.send();
// System.out.println("_end");
//
// Notifier e1 = new EmailNotifier();
// e1.send();
// System.out.println("_end");
//
// Notifier s1 = new SmsNotifier();
// s1.send();
// System.out.println("_end");
/*-------데코레이터-------*/
// 1. 이메일 알림
EmailNotifier n1 = new EmailNotifier();
n1.send();
System.out.println();
// 2. 기본 알림 + 이메일 알림
EmailNotifier n2 = new EmailNotifier(new BasicNotifier());
n2.send();
System.out.println();
// 3. 문자 알림 + 이메일 알림
EmailNotifier n3 = new EmailNotifier(new SmsNotifier());
n3.send();
System.out.println();
// 4. 문자알림
SmsNotifier n4 = new SmsNotifier();
n4.send();
System.out.println();
// 5. 문자알림 + 이메일알림 + 기본알림
SmsNotifier n5 = new SmsNotifier(new EmailNotifier(new BasicNotifier()));
n5.send();
System.out.println();
// 6. 문자알림 + 문자알림 + 이메일알림 + 기본알림
SmsNotifier n6 = new SmsNotifier(new SmsNotifier(new EmailNotifier(new BasicNotifier())));
ClientNotification.send(n6);
System.out.println();
}
}

Share article