정의
객체에 동적으로 새로운 기능을 추가할 수 있게 해주는 구조적 디자인 패턴.
상속을 통해서 기능을 확장하는 것보다 더 유연해 질 수 있음
데코레이터 패턴은 주로 기존 클래스의 코드를 수정하지 않고도 추가적인 기능을 제공하고 싶을 때 사용
예제
public interface Notifier {
void send();
}
public class BasicNotifier implements Notifier{
Notifier notifier;
public BasicNotifier() {
}
public BasicNotifier(Notifier notifier) {
this.notifier = notifier;
}
public void send(){
if ( notifier != null){
notifier.send();
}
System.out.println("기본 알림");
}
}
public class EmailNotifier implements Notifier{
Notifier notifier;
public EmailNotifier() {
}
public EmailNotifier(Notifier notifier) {
this.notifier = notifier;
}
@Override
public void send(){
if(notifier != null){
notifier.send();
}
System.out.println("이메일 알림");
}
}
public class SmsNotifier implements Notifier{
Notifier notifier;
public SmsNotifier() {
}
public SmsNotifier(Notifier notifier) {
this.notifier = notifier;
}
@Override
public void send() {
if(notifier != null) {
notifier.send();
}
System.out.println("SMS 알림");
}
}
public class App {
public static void 알림(Notifier notifier){
notifier.send();
}
// 데코레이터 패턴 -> 기능 확장
public static void main(String[] args) {
// 1. 전체 알림(기본 알림 -> 문자 알림 -> 이메일 알림)
Notifier notifier = new BasicNotifier(new SmsNotifier(new EmailNotifier()));
알림(notifier);
// 2. 전체 알림(기본 알림 -> 이메일 알림 -> 문자 알림)
Notifier notifier2 = new BasicNotifier(new EmailNotifier(new SmsNotifier()));
알림(notifier2);
// 3. 기본 알림
Notifier notifier3 = new BasicNotifier();
알림(notifier3);
// 4. 기본 알림 - 문자 알림
Notifier notifier4 = new BasicNotifier(new SmsNotifier());
알림(notifier4);
// 5. 기본 알림 - 이메일 알림
Notifier notifier5 = new BasicNotifier(new EmailNotifier());
알림(notifier5);
// 6. 이메일 알림
Notifier notifier6 = new EmailNotifier();
알림(notifier6);
// 7. 문자 알림
Notifier notifier7 = new SmsNotifier();
알림(notifier7);
// 8. 문자 알림 - 이메일 알림
Notifier notifier8 = new SmsNotifier(new EmailNotifier());
알림(notifier8);
}
}
구성
- 컴포넌트(Component): 데코레이터와 구체적인 객체가 구현해야 하는 공통 인터페이스 또는 추상 클래스
- 구체적인 컴포넌트(ConcreteComponent): 기본 기능을 구현하는 클래스
- 데코레이터(Decorator): 컴포넌트 인터페이스를 구현하며, 구체적인 컴포넌트를 포함하여 추가 기능을 제공하는 추상 클래스
- 구체적인 데코레이터(ConcreteDecorator): 데코레이터 클래스의 구체적인 구현으로, 추가 기능을 제공
장점
- 유연한 기능 확장 : 기존 코드를 수정하지 않고도 객체에 새로운 기능을 추가 할 수 있음
- 단일 책임 원칙 준수 : 클래스의 책임을 분리할 수 있음. 각각의 데코레이터는 추가적인 기능만을 담당하여 클래스가 하나의 책임만 가질 수 있음
- 객체 합성 : 객체 합성을 사용하여 기능을 확장. 컴파일 시에 상속 구조를 결정하는 것보다 런타임에 동적으로 기능을 결합하는 것을 가능
- 유지보수 용이 : 새로운 기능을 추가하거나 기존 기능을 변경할 때, 데코레이터만 수정하면 되므로 유지보수가 용이
단점
- 복잡성 증가 : 클래스 수가 증가하여 코드가 복잡해짐
- 디버깅 어려움 : 데코레이터가 여러 겹으로 쌓일 경우, 디버깅이 어려움
- 런타임 비용 : 직접적인 호출보다 런타임 비용이 약간 증가
- 객체 식별 문제 : 데코레이터가 감싸고 있는 객체를 식별하기 어려움. 특정 객체를 직접 접근할 때 문제가 생길 수 있음
Share article