inblog logo
|
DailyCoding
    Spring Boot

    13-6. 데코레이터 패턴 (Decorator Pattern)

    박은서's avatar
    박은서
    Feb 24, 2026
    13-6. 데코레이터 패턴 (Decorator Pattern)
    Contents
    1. 데코레이터 패턴 (Decorator Pattern)1️⃣ 데코레이터 패턴이란?2️⃣ 목적3️⃣ 구조4️⃣ 작동 원리 (How It Works)5️⃣ 언제 사용하나? (When To Use)6️⃣ 데코레이터 패턴의 장단점7️⃣ 예제8️⃣ 코드 예시2. 실습 (ex06)1️⃣ 테스트용2️⃣ 인터페이스 추가3️⃣ 데코레이터 패턴4️⃣ EXAM

    1. 데코레이터 패턴 (Decorator Pattern)

    1️⃣ 데코레이터 패턴이란?

    1) 개념

    객체에 동적으로 새로운 책임(기능)을 추가할 수 있도록 하는 구조 패턴

    2) 핵심 아이디어

    • 상속 대신 객체 합성(composition) 사용
    • 기존 클래스 수정 없이 기능 확장
    • 객체를 "포장(wrapping)" 방식으로 기능 추가

    2️⃣ 목적

    데코레이터 패턴은 다음 문제 해결
    • 기능 조합이 많아질 때 상속 폭발 방지
    • 런타임에 기능 확장 가능
    • 기존 코드 변경 최소화 (OCP 준수)
    ➡️ "기능 확장 유연성 확보"

    3️⃣ 구조

    1) 주요 구성 요소

    구성 요소
    설명
    Component
    공통 인터페이스
    ConcreteComponent
    기본 객체
    Decorator
    Component 인터페이스 구현 + Component 참조
    ConcreteDecorator
    실제 기능 추가

    2) 구조적 관계

    Component (interface) ↑ ConcreteComponent Component (interface) ↑ Decorator → Component 참조 ↑ ConcreteDecorator
    • 데코레이터는 Component 타입을 감싼다
    • 인터페이스가 동일 → 투명한 확장

    4️⃣ 작동 원리 (How It Works)

    1. 기본 객체 생성
    1. 데코레이터로 감싼다
    1. 필요하면 여러 번 감싼다
    객체 = 기능A(기능B(기본객체))
    ➡️ 기능을 레이어처럼 누적

    5️⃣ 언제 사용하나? (When To Use)

    • 런타임에 기능 확장이 필요할 때
    • 상속이 비효율적일 때
    • 기능 조합이 많을 때
    • 클래스 수정 없이 확장해야 할 때

    6️⃣ 데코레이터 패턴의 장단점

    1) 장점

    • 상속 대체 가능
    • 기능 조합 유연성
    • 기존 코드 변경 없음 (OCP)
    • 책임 분리 가능
    • 단일 책임 원칙(SRP) 강화

    2) 단점

    • 객체 수 증가
    • 디버깅 복잡도 증가
    • 구조 이해 어려움
    • 설정 코드가 장황해질 수 있음

    7️⃣ 예제

    1) ☕ 커피 주문 시스템

    • 기본 객체
      • SimpleCoffee → 가격: 3000원
    • 데코레이터 적용
      • MilkDecorator → +500원 WhipDecorator → +700원
    • 조합 결과
      • Whip(Milk(SimpleCoffee)) → 3000 + 500 + 700
    ➡️ 기능을 자유롭게 조합 가능

    8️⃣ 코드 예시

    // Component interface Coffee { int cost(); } // ConcreteComponent class SimpleCoffee implements Coffee { public int cost() { return 3000; } } // Decorator abstract class CoffeeDecorator implements Coffee { protected Coffee coffee; CoffeeDecorator(Coffee coffee) { this.coffee = coffee; } } // ConcreteDecorator class MilkDecorator extends CoffeeDecorator { MilkDecorator(Coffee coffee) { super(coffee); } public int cost() { return coffee.cost() + 500; } }

    2. 실습 (ex06)

    1️⃣ 테스트용

    1) BasicNotifier.java

    C:\workspace\java_lab\designapp\src\ex06\notification\BasicNotifier.java
    package ex06.notification; public class BasicNotifier { public void send() { System.out.println("기본 알림"); } }

    2) App.java

    C:\workspace\java_lab\designapp\src\ex06\App.java
    package ex06; import ex06.notification.BasicNotifier; public class App { public static void main(String[] args) { BasicNotifier b1 = new BasicNotifier(); b1.send(); } }

    3) 결과

    notion image

    4) EmailNotifier.java

    C:\workspace\java_lab\designapp\src\ex06\notification\EmailNotifier.java
    package ex06.notification; public class EmailNotifier { public void send() { System.out.println("이메일 알림"); } }

    5) App.java

    C:\workspace\java_lab\designapp\src\ex06\App.java
    package ex06; import ex06.notification.BasicNotifier; import ex06.notification.EmailNotifier; public class App { public static void main(String[] args) { EmailNotifier b1 = new EmailNotifier(); BasicNotifier b2 = new BasicNotifier(); b1.send(); b2.send(); } }

    6) 결과

    notion image

    2️⃣ 인터페이스 추가

    메서드 실수하지 않게 인터페이스로 제약!

    1) Notifier.java (인터페이스)

    C:\workspace\java_lab\designapp\src\ex06\notification\Notifier.java
    package ex06.notification; public interface Notifier { void send(); }

    2) BasicNotifier.java

    package ex06.notification; public class BasicNotifier implements Notifier { public void send() { System.out.println("기본 알림"); } }

    3) EmailNotifier.java

    package ex06.notification; public class EmailNotifier implements Notifier { public void send() { System.out.println("이메일 알림"); } }

    4) SmsNotifier.java

    C:\workspace\java_lab\designapp\src\ex06\notification\SmsNotifier.java
    package ex06.notification; public class SmsNotifier implements Notifier{ @Override public void send() { System.out.println("문자 알림"); } }

    3️⃣ 데코레이터 패턴

    1) BasicNotifier.java

    package ex06.notification; public class BasicNotifier implements Notifier { private Notifier notifier; // 뭐든지 has 할 수 있다(모든 것이 Notifier를 상속하고 있기 때문) public BasicNotifier() {} public BasicNotifier(Notifier notifier) { this.notifier = notifier; } public void send() { if (notifier != null) notifier.send(); System.out.println("기본 알림"); } }

    2) App.java

    package ex06; import ex06.notification.BasicNotifier; import ex06.notification.EmailNotifier; import ex06.notification.SmsNotifier; /** * { * "sends" : [basic, email], * "msg": "반가워!!" * } */ // 책임 : 기존에 있는 클래스에 기능을 확장하면서 계속 추가하는 패턴 public class App { public static void main(String[] args) { BasicNotifier b1 = new BasicNotifier(new SmsNotifier()); b1.send(); } }

    3) 결과

    notion image

    4) EmailNotifier.java

    package ex06.notification; public class EmailNotifier implements Notifier { private Notifier notifier; // 뭐든지 has 할 수 있다(모든 것이 Notifier를 상속하고 있기 때문) public EmailNotifier() {} public EmailNotifier(Notifier notifier) { this.notifier = notifier; } public void send() { if (notifier != null) notifier.send(); System.out.println("이메일 알림"); } }

    5) SmsNotifier.java

    package ex06.notification; public class SmsNotifier implements Notifier{ private Notifier notifier; // 뭐든지 has 할 수 있다(모든 것이 Notifier를 상속하고 있기 때문) public SmsNotifier() {} public SmsNotifier(Notifier notifier) { this.notifier = notifier; } public void send() { if (notifier != null) notifier.send(); System.out.println("문자 알림"); } }

    4️⃣ EXAM

    1) App.java

    package ex06; import ex06.notification.BasicNotifier; import ex06.notification.EmailNotifier; import ex06.notification.SmsNotifier; /** * { * "sends" : [basic, email], * "msg": "반가워!!" * } */ // 책임 : 기존에 있는 클래스에 기능을 확장하면서 계속 추가하는 패턴 public class App { public static void main(String[] args) { // 1번 문제 (SMS 알림, SMS 알림, Email 알림) EmailNotifier b1 = new EmailNotifier(new SmsNotifier(new SmsNotifier())); b1.send(); System.out.println("-----------------------------------------"); // 2번 문제 (기본 알림, SMS 알림, Email 알림) EmailNotifier b2 = new EmailNotifier(new SmsNotifier(new BasicNotifier())); b2.send(); System.out.println("-----------------------------------------"); // 3번 문제 (SMS 알림) SmsNotifier b3 = new SmsNotifier(); b3.send(); } }

    2) 결과

    notion image
    Share article
    Contents
    1. 데코레이터 패턴 (Decorator Pattern)1️⃣ 데코레이터 패턴이란?2️⃣ 목적3️⃣ 구조4️⃣ 작동 원리 (How It Works)5️⃣ 언제 사용하나? (When To Use)6️⃣ 데코레이터 패턴의 장단점7️⃣ 예제8️⃣ 코드 예시2. 실습 (ex06)1️⃣ 테스트용2️⃣ 인터페이스 추가3️⃣ 데코레이터 패턴4️⃣ EXAM

    DailyCoding

    RSS·Powered by Inblog