![[디자인 패턴] 7. Decorator 패턴](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255B%25EB%2594%2594%25EC%259E%2590%25EC%259D%25B8%2520%25ED%258C%25A8%25ED%2584%25B4%255D%25207.%2520Decorator%2520%25ED%258C%25A8%25ED%2584%25B4%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3Djay0628&w=2048&q=75)
Contents
예제 - 알림 보내기
책임 분리하고 ~하고 나서 패턴 적용 (SOLID가 적용되고 난 뒤에 패턴을 적용한다 = 전략 패턴을 지키고 나서 패턴 적용한다)
데코레이터 패턴의 목적은 기능의 확장이다.
그럼 상속 아닌가? 라는 생각이 들 수 있다.
예제 - 알림 보내기
1단계
DIP고 OCP고 뭐고 생각하고 설계하고 만들지 말자. 처음에는 일단 만들어야 한다.


이메일 알림 클래스는 팀원이 만들었다고 가정하자. 즉 나는 아래의 코드를 모르고 있는 상황이다.

이메일 알림을 쓰려고 하니까 send가 없네? 지금은 툴이 있으니까 알 수 있지만 이전에는 모르거나 send라는 일관성이 없다.
강제성을 주기 위해 추상 메서드를 사용한다. 이때 인터페이스든 추상 클래스든 상관 없다. 따라서 추상 메서드를 쓰게 되면 강제성이 부여되는 것 뿐만 아니라 추상화까지 적용된다.






2단계 : email 알림과 기본 알림을 같이 보내고 싶어!



⇒ 2번 호출이 아니라 한 번의 호출로 이메일과 기본 알림 둘 다 보낼 수 있도록 해주는게 데코레이터 패턴!
3단계 : 데코레이터 패턴을 적용해보자
notifier가 notifier를 has해서 재귀적으로 해결 가능하다.
1. 이메일 알림



null 넣는거 불편ㅠ → 기본 생성자를 만들자


2. 기본 + 이메일, 문자 + 이메일

3. 문자 알림 + 이메일 알림 + 기본 알림
기본 알림에는 없는게 좋음 끝이 잇어야 하니께..

4. 문자 알림 + 문자 알림 + 이메일 알림 + 기본 알림

5. 이제 저 선택 값들을 가지고 어떻게 객체를 만들지?
- for문 돌리기
- reflection
{
"userId" : 5,
"notiTypeList" : ["sms", "sms", "email", "basic"]
}


그래서 reflection을 적용한다면?
package ex06;
import ex06.notification.Notifier;
import java.util.List;
public class App {
public static void main(String[] args) throws Exception {
List<String> notiTypeList = List.of("sms", "sms", "email", "basic");
Notifier chain = NotifierFactory.buildNotifierChain(notiTypeList);
ClientNotification.send(chain);
}
}
package ex06;
import ex06.notification.Notifier;
import java.util.List;
public class NotifierFactory {
public static Notifier buildNotifierChain(List<String> typeList) throws Exception {
Notifier chain = null;
for (int i = typeList.size() - 1; i >= 0; i--) {
String type = typeList.get(i);
String className = "ex06.notification." + capitalize(type) + "Notifier";
Class<?> clazz = Class.forName(className);
if (chain == null) {
chain = (Notifier) clazz.getDeclaredConstructor().newInstance();
} else {
chain = (Notifier) clazz.getDeclaredConstructor(Notifier.class).newInstance(chain);
}
}
return chain;
}
private static String capitalize(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
구조
App → 프로그램 실행 시작 └─> NotifierFactory → 알림 체인을 생성 └─> ClientNotification.send() → 알림 전송
Share article