본문 바로가기
java/디자인패턴

프록시, 데코레이터 패턴

by 문자메일 2022. 10. 9.

프록시 패턴과 데코레이터 패턴 모두 프록시를 사용하는 방법이지만 GOF 디자인 패턴에서는 이 둘을 의도에 따라서 프록시 패턴과 데코레이터 패턴으로 구분한다.

- 프록시 패턴 : 접근 제어가 목적일 때

- 데코레이터 패턴 : 새로운 기능 추가가 목적일 때

 

 

프록시의 주요 기능

프록시를 통해서 할 수 있는 일은 크게 2가지로 구분할 수 있다.

  • 접근 제어
    • 권한에 따른 접근 차단
    • 캐싱
    • 지연로딩
  • 부가 기능 추가
    • 원래 서버가 제공하는 기능에 더해서 부가 기능을 수행한다.
    • ex : 요청 값이나, 응답 값을 중간에서 변경하거나
    • ex : 실행 시간을 측정해서 추가 로그를 남기거나

 

 

프록시 패턴 코드

정리 : 프록시 패턴의 핵심은 RealSubject 코드와 클라이언트 코드를 전혀 변경하지 않고, 프록시를 도입해서 접근 제어를 했다는 점이다. 그리고 클라이언트 코드의 변경 없이 자유롭게 프록시를 넣고 뺄 수 있다. 실제 클라이언트 입장에서는 프록시 객체가 주입되었는지, 실제 객체가 주입되었는지 알지 못한다.

 

public interface Subject {
    String operation();
}
@Slf4j
public class RealSubject implements Subject{
    @Override
    public String operation() {
        log.info("실제 객체 호출");
        sleep(1000);
        return "data";
    }

    private void sleep(int millis){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
@Slf4j
public class CacheProxy implements Subject{

    private Subject target;
    private String cacheValue;


    public CacheProxy(Subject target) {
        this.target = target;
    }

    @Override
    public String operation() {
        log.info("프록시 호출");
        if(cacheValue==null){
            cacheValue = target.operation();
        }
        return cacheValue;
    }
}
public class ProxyPatternClient {
    private Subject subject;

    public ProxyPatternClient(Subject subject) {
        this.subject = subject;
    }

    public void execute(){
        subject.operation();
    }
}
public class ProxyPatternTest {
    @Test
    void noProxyTest(){
        RealSubject realSubject = new RealSubject();
        ProxyPatternClient client = new ProxyPatternClient(realSubject);
        client.execute();
        client.execute();
        client.execute();
    }

    @Test
    void cacheProxyTest(){
        RealSubject realSubject = new RealSubject();
        CacheProxy cacheProxy = new CacheProxy(realSubject);
        ProxyPatternClient client = new ProxyPatternClient(cacheProxy);
        client.execute();
        client.execute();
        client.execute();
    }
}

 

------------------

아래는 데코레이터 패턴 예제

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

    private Component component;

    public MessageDecorator(Component component) {
        this.component = component;
    }

    @Override
    public String operation() {
        log.info("MessageDecorator 실행");

        String result = component.operation();
        String decoResult = "*****" + result + "*****";
        log.info("MessageDecorator 꾸미기 적용 전 ={}, 적용 후={}", result, decoResult);
        return decoResult;
    }
}
@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);
    }
}
@Slf4j
public class DecoratorPatternTest {
    @Test
    void noDecorator(){
        Component realComponent = new RealComponent();
        DecoratorPatternClient client = new DecoratorPatternClient(realComponent);
        client.execute();
    }

    @Test
    void decorator1(){
        Component realComponent1 = new RealComponent();
        Component messageDecorator = new MessageDecorator(realComponent1);
        DecoratorPatternClient client = new DecoratorPatternClient(messageDecorator);
        client.execute();
    }

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

}

'java > 디자인패턴' 카테고리의 다른 글

팩토리 메서드 패턴  (0) 2023.02.14
어뎁터 패턴 (adapter pattern)  (0) 2023.02.03
전략 패턴, 템플릿 콜백 패턴  (0) 2022.10.08
전략 패턴  (0) 2022.10.03
템플릿 메서드 패턴  (0) 2022.10.02

댓글