Design pattern 7. Decorator Pattern

김미숙's avatar
Jul 23, 2025
Design pattern 7. Decorator Pattern
💡
최종 보스
notion image
 

✅ 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(); } }
notion image
Share article

parangdajavous