ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 데코레이터 패턴
    스프링/스프링 AOP 2023. 9. 10. 16:53

    데코레이터 패턴은 프록시를 사용하는 디자인 패턴 중에서 부가 기능을 추가시켜주는 패턴이다.

     

     

    Component 인터페이스

    public interface Component {
        String operation();
    }

     

    Component의 구현체인 RealCcomponent

    @Slf4j
    public class RealComponent implements Component {
        @Override
        public String operation() {
            log.info("RealComponent 실행");
            return "data";
        }
    }

     

     

    client 계층 - DecoratorPatternClient

    @Slf4j
    public class DecoratorPatternClient {
    
        private Component component;
    
        public DecoratorPatternClient(Component component) {
            this.component = component;
        }
    
        public void execute() {
            String result = component.operation();
            log.info("result={}", result);
        }
    }

    data를 실행시켜주는 로직이다. 이렇게만 구현해놓으면 정상적으로 실행이 될 것이다. 이제 여기다가 부가기능을 추가할 것이다.

     

    사진 : 인프런 스프링 강의

    위의 사진처럼 구현을 할 것인데 프록시를 체인 형태로 만들어서 로직을 수행하는데 걸리는 시간과 message를 꾸며주는 부가기능을 넣을 것이다.

     

     

    첫 번째 프록시 - TimeDecorator

    @Slf4j
    public class TimeDecorator implements Component {
    
        private Component component;
    
        public TimeDecorator(Component component) {
            this.component = component;
        }
    
        @Override
        public String operation() {
            log.info("TimeDecorator 실행");
            long startTime = System.currentTimeMillis();
    
            String result = component.operation();
    
            long endTime = System.currentTimeMillis();
            long resultTime = endTime - startTime;
            log.info("TimeDecorator 종료 resultTIme={}ms", resultTime);
            return result;
        }
    }

    로직 수행 시간을 알려주는 TimeDecorator이다. operation() 메서드에서 component의 operation()을 호출하면서 로직 수행 시 걸리는 시간을 계산해서 로그로 출력해준다.

     

     

    두 번째 프록시 - MessageDecorator

    @Slf4j
    public class MessageDecorator implements Component {
    
        private Component component;
    
        public MessageDecorator(Component component) {
            this.component = component;
        }
    
        @Override
        public String operation() {
            log.info("MessageDecorator 실행");
    
            // data -> *****data*****
            String result = component.operation();
            String decoResult = "*****" + result + "*****";
            log.info("MessageDecorator 꾸미기 적용 전={}, 적용 후={}", result, decoResult);
            return decoResult;
        }
    }

    두 번째로 반환되는 데이터의 앞 뒤에 별을 다섯개 씩 붙여주는 로직이다. 별로 의미는 없지만, 부가적인 기능을 프록시로 넣을 수 있고, 체인으로 여러 프록시를 결합할 수 있다는 것을 확인하기 위해 추가했다.

     

     

     

    테스트 코드

    @Test
    void decorator() {
        Component realComponent = new RealComponent();
        Component messageDecorator = new MessageDecorator(realComponent);
        Component timeDecorator = new TimeDecorator(messageDecorator);
        DecoratorPatternClient client = new DecoratorPatternClient(timeDecorator);
        client.execute();
    }

    client -> timeDecorator -> messageDecorator -> realComponent 순으로 호출이 진행된다.

     

    실행을 해보면 위와 같이 결과가 나오게 되는데, 2개의 프록시가 모두 적용된 것을 확인할 수 있다.

     

     

    사진 : 인프런 스프링 강의

    의존 관계는 위의 사진과 같은데, 모두 Component 인터페이스를 구현하고 있는 것이다.

     

     

    데코레이터 패턴도 프록시 패턴과 마찬가지로 클라이언트 코드가 프록시를 호출하는지, 실제 RealComponent를 호출하는지 모르며 클라이언트 코드를 변경하지 않아도 된다는 큰 장점이 있다.

     

     

     

     

    Decorator 중간 인터페이스로 Decorator와 실제 기능 분리

    사진 : 인프런 스프링 강의

    Component를 구현하는 구현체 중에서 Decorator라는 인터페이스를 또 만들고 그것의 구현체들을 프록시로 두는 방법이 있다.

    이 방법을 사용하면

    1. 실제 기능, 데코레이터를 쉽게 구분 가능

    2. 데코레이터의 중복 코드를 Decorator에 넣을 수 있음

Designed by Tistory.