참고 1. 스프링-핵심-원리-고급편, 김영한
참고 2. 위키백과
프록시/데코레이터 체이닝
프록시/데코레이터 패턴은 여러 번 중첩시킬 수 있는데, 이를 체이닝이라고 한다. 아래 사진의 '프록시 패턴 Ex.2'에 해당하는 3번째 구조가 체이닝의 예이다.
아래 그림과 같이 각 프록시/데코레이터는 동일한 인터페이스를 상속받으며, 각 프록시/데코레이터들은 순차적으로 이전 객체를 주입받아 순차적으로 연결된다.
예제
아래는 동작 시간을 측정해주는 데코레이터와 로그를 리포멧팅 해주는 데코레이터를 체이닝한 예제이다.
1. 인터페이스 정의
public interface Component {
String operation();
}
2. 문자열관련 데코레이터
@Slf4j
public class MessageDecorator implements Component {
private Component component;
public MessageDecorator(Component component) {
this.component = component;
}
@Override
public String operation() {
String result = component.operation();
String decoResult = "----> " + result + " <----";
log.info("MessageDeco 적용전={}", result);
log.info("MessageDeco 적용후={}", decoResult);
return decoResult;
}
}
3. 실행시간 측정 데코레이터
@Slf4j
public class TimeDecorator implements Component{
private Component component;
public TimeDecorator(Component component) {
this.component = component;
}
@Override
public String operation() {
long startMs = System.currentTimeMillis();
String result = component.operation();
long endMs = System.currentTimeMillis();
log.info("실행 시간={}", endMs - startMs);
return result;
}
}
4. 서버 기능 (원본 서버)
@Slf4j
public class RealComponent implements Component{
@Override
public String operation() {
log.info("RealComponent 실행");
return "data";
}
}
5. 실행 예시
- 위에서 정의한 실제 서버, 메시지 데코레이터, 타임 데코레이터들을 순서에 맞게 생성자 주입으로 연결 시켜준다. 아래와 같이 연결하게 되면, Client ➡️ TimeDecorator ➡️ MessageDecorator ➡️ RealComponent 순으로 진입한다.
- 진입 순서 : Client ➡️ TimeDecorator ➡️ MessageDecorator ➡️ RealComponent
@Test
void Decorator2() {
Component realComponent = new RealComponent();
Component MessageDeco = new MessageDecorator(realComponent);
Component timeDecorator = new TimeDecorator(MessageDeco);
DecoratorPatternClient client = new DecoratorPatternClient(timeDecorator);
client.execute();
}
아래는 실행 결과 모습이다.