오봉이와 함께하는 개발 블로그

스프링 핵심 원리 - 고급편 > 데코레이터 본문

BE/Spring

스프링 핵심 원리 - 고급편 > 데코레이터

오봉봉이 2024. 8. 25. 22:03
728x90

스프링 고급편 - Decorator

데코레이터 패턴 이해를 위한 예제 코드를 작성하기 전 클래스 의존 관계를 보자

  • 클래스 의존 관계
    • Client -> Component <- RealComponent
  • 런타임 의존 관계
    • Client -> RealComponent
public interface Component {
  String operation();
}
@Slf4j
public class RealComponent implements Component {

  @Override
  public String operation() {
    log.info("run RealComponent");
    return "data";
  }
}
@Slf4j
@RequiredArgsConstructor
public class DecoratorPatternClient {

  private final Component component;

  public void execute() {
    String result = component.operation();
    log.info("result = {}", result);
  }
}
  @Test
  void noDecorator() {
    RealComponent realComponent = new RealComponent();
    DecoratorPatternClient client = new DecoratorPatternClient(realComponent);
    client.execute();
  }

부가 기능 추가 1

이제 데코레이터 패턴을 통해 부가 기능을 추가해보자.
이전 프록시를 통해서는 캐시를 통해 접근 제어를 해봤다.
이렇게 프록시를 통해 부가 기능을 추가하는 것을 데코레이터라고 한다.

데코레이터 패턴 적용 후 클래스 의존 관계

image

데코레이터 패턴 적용 후 런타임 의존 관계

image

@Slf4j
@RequiredArgsConstructor
public class DecoratorPatternClient {

  private final Component component;

  public void execute() {
    String result = component.operation();
    log.info("result = {}", result);
  }
}
  @Test
  void decorator1() {
    RealComponent realComponent = new RealComponent();
    MessageDecorator messageDecorator = new MessageDecorator(realComponent);
    DecoratorPatternClient client = new DecoratorPatternClient(messageDecorator);
    client.execute();
  }
21:53:57.454 [main] INFO hello.proxy.pureproxy.decorator.code.MessageDecorator - run message decorator
21:53:57.455 [main] INFO hello.proxy.pureproxy.decorator.code.RealComponent - run RealComponent
21:53:57.457 [main] INFO hello.proxy.pureproxy.decorator.code.MessageDecorator - Message Decorator 적용 전 = data / 적용 후 = *****data*****
21:53:57.458 [main] INFO hello.proxy.pureproxy.decorator.code.DecoratorPatternClient - result = *****data*****

프록시 코드와 다른 것이 보이지 않지만, 프록시가 수행하는 기능에 따라 이름이 나뉘어 불린다.

부가 기능 추가 2

이제 기존 데코레이터에 실행 시간을 측정하는 기능까지 추가해보자.

클래스 의존 관계

image

런타임 의존 관계

image

@Slf4j
@RequiredArgsConstructor
public class MessageDecorator implements Component {

  private final Component component;

  @Override
  public String operation() {
    log.info("run message decorator");
    String realOperation = component.operation();
    String decoResult = "*****" + realOperation + "*****";
    log.info("Message Decorator 적용 전 = {} / 적용 후 = {}", realOperation, decoResult);
    return decoResult;
  }
}
  @Test
  void decorator2() {
    RealComponent realComponent = new RealComponent();
    MessageDecorator messageDecorator = new MessageDecorator(realComponent);
    TimeDecorator timeDecorator = new TimeDecorator(messageDecorator);
    DecoratorPatternClient client = new DecoratorPatternClient(timeDecorator);
    client.execute();
  }
21:59:25.399 [main] INFO hello.proxy.pureproxy.decorator.code.TimeDecorator - Run Time Decorator
21:59:25.400 [main] INFO hello.proxy.pureproxy.decorator.code.MessageDecorator - run message decorator
21:59:25.400 [main] INFO hello.proxy.pureproxy.decorator.code.RealComponent - run RealComponent
21:59:25.402 [main] INFO hello.proxy.pureproxy.decorator.code.MessageDecorator - Message Decorator 적용 전 = data / 적용 후 = *****data*****
21:59:25.403 [main] INFO hello.proxy.pureproxy.decorator.code.TimeDecorator - Time Decorator 종료 ResultTime = 3ms
21:59:25.403 [main] INFO hello.proxy.pureproxy.decorator.code.DecoratorPatternClient - result = *****data*****

이전 코드들과 동일하게 원본에 수정이 없이 부가 기능을 추가하여 시간을 넣었다.

 

출처: 김영한 지식공유자의 스프링 핵심 원리 고급편

728x90
Comments