본문 바로가기

카테고리 없음

[Spring] 디자인 패턴 - 프록시/데코레이터 체이닝

참고 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();
}

 

아래는 실행 결과 모습이다.

실행 결과