Contents
Decorator PatternDecorator Pattern
- 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴
책임을 추가하는 방법
- 상속 (extends) : 하나의 클래스밖에 상속받을 수 없음
- 컴퍼지션 : 코드 수정 시 전체 코드를 다 수정해야 함 (OCP 위배)
- 추상 메서드 + 추상 클래스 or 인터페이스 : 추상화를 통한 DIP + OCP + 코드 구현의 강제성 부여 가능
- 인터페이스 + 컴퍼지션 조합이 제일 이상적인 데코레이터 패턴
Ex. 알림 보내기
- 사용자에게 어떤 메시지를 보내려고 할 때, 기본 / 이메일 / 문자의 방법을 사용해서 보내고 싶음
- 1개씩 선택하거나, 2개씩 선택하거나, 전부 다 선택하는 방법도 존재
Q1. 조건문으로 만든다면?
- 위 예제에서는 선택지가 3개밖에 없다 해도 총 경우의 수는 7개가 존재
- 실제로 선택지가 늘어나게 되면 해당 경우의 수에 따라 케이스를 모두 만들어야 함
- 케이스 예상을 할 수 없고 책임이 증가하게 됨 (SRP 위반)
Q2. 데코레이터 패턴을 사용하면?
- 각 알림을 보내기 위한 Notifier를 구현 (Basic, Email, SMS)
- 추상화를 위한 Notifier 인터페이스 구현 및 각 Notifier들에게 연결
- Notifier에서 작성하였던 추상 메서드를 구현해야 하므로 코드의 컨벤션 또한 지켜짐
- 내부 함수에서 Notifier의 알림 전송 메서드 호출
- 실행 시 필요한 Notifier들을 연쇄 호출 (Notifier의 함수에 직접 접근하지 않고 Adapter 등 사용)
- 필요한 Notifier들을 Static Factory 등을 사용하여 호출할 수 있음

코드
- App.java
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 e1 = new EmailNotifier();
e1.send();
System.out.println("_end");
// 2. 이메일 + 기본 알림
EmailNotifier e2 = new EmailNotifier(new BasicNotifier());
e2.send();
System.out.println("_end");
// 3. 이메일 + 문자 알림
EmailNotifier e3 = new EmailNotifier(new SMSNotifier());
e3.send();
System.out.println("_end");
// 4. 문자 + 기본 알림
SMSNotifier s1 = new SMSNotifier(new BasicNotifier());
s1.send();
System.out.println("_end");
// 5. 문자 + 이메일 + 기본 알림
Notifier n1 = new SMSNotifier(new EmailNotifier(new BasicNotifier()));
n1.send();
System.out.println("_end");
// 6. 문자 2번 -> 이메일 1번 -> 기본 알림
Notifier n2 = new SMSNotifier(new SMSNotifier(new EmailNotifier(new BasicNotifier())));
ClientNotification.noti(n2);
}
}
- ClientNotification.java
public class ClientNotification {
public static void noti(Notifier notifier) {
notifier.send();
}
}
- Notifier.java
// 팀원이 만든 코드와 내가 만든 코드의 일관성이 깨짐
// 강제성 부여 필요 : 추상 메서드 (인터페이스 or 추상 클래스) -> 자동 추상화
public interface Notifier {
void send();
}
- BasicNotifier.java
public class BasicNotifier implements Notifier {
public void send() {
System.out.println("기본 알림");
}
}
- EmailNotifier.java
- Notifier를 컴퍼지션으로 사용 : Notifier 연쇄 호출 가능
- 기본 생성자 : notifier가 null일 경우 연쇄 호출 중단
public class EmailNotifier implements Notifier {
private Notifier notifier;
public EmailNotifier() {
}
public EmailNotifier(Notifier notifier) {
this.notifier = notifier;
}
@Override
public void send() {
System.out.println("이메일 알림");
if(notifier != null) {notifier.send();}
}
}
- SMSNotifier.java
public class SMSNotifier implements Notifier {
public SMSNotifier() {
}
private Notifier notifier;
public SMSNotifier(Notifier notifier) {
this.notifier = notifier;
}
@Override
public void send() {
System.out.println("문자 알림");
if(notifier != null) {notifier.send();}
}
}
Share article