본문 바로가기

개인공부/디자인패턴

프록시 패턴 / 데코레이터 패턴

반응형

프록시란?

 

서버 이야기를 하다보면 프록시라는게 존재한다. 프록시는 클라이언트에서 서버를 호출할 때 들리는 일종의 중간 문이라고 생각하고 그 과정에서 여러가지 정보를 수정하거나 로그를 찍거나 할 수 있다.

 

프록시 패턴에서 프록시도 서버에서 말하는 프록시와 그 기능이 동일하다.

 

프록시 패턴 (접근제어, 캐싱)

어떠한 인터페이스 Subject라고 하는 인터페이스의 구현체라고 가정한다.

 

Subject Interface

public interface Subject {
    String operation();
}

 

해당 인터페이스를 구현하고 있는 현재 사용하고 있는 인스턴스이다.

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

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

이제 프록시 객체를 구현할 것인데 클라이언트는 Subject 인터페이스를 의존하고 있다. 

 

이때 프록시는 Client에서 호출하는 Subject : RealSubject를 대체 할 수 있어야한다. (DI를 사용해서 대체가 가능해야 한다.)

 

해당 그림도 구글에서 주워 왔는데 RealSubject와 Proxy는 같은 인터페이스의 구현체가 되었고 Proxy는 클라이언트에서 호출하는 RealSubejct와 대체 될 수 있어야한다.

 

이게 무슨말이냐... 

 

public class ProxyPatternClient {

    private Subject subject;

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

    public void execute() {
        subject.operation();
    }
}

ProxyPatternClient는 Subject 인터페이스를 변수로 가지고 있고 생성시에 외부에서 subject를 주입받는다.

 

이때 subject는 RealSubject를 주입받게 되고 execute를 통해서 RealSubejct를 실행하게 된다. 이때 프록시 패턴 캐시를 추가해보자.

 

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;
    }
}

캐시 프록시는 RealSubject와 마찬가지고 Subject를 인터페이스로 implements 한다. 중요한것은 생성시에 target(Subject) 를 주입받게 되고 operation을 호출하면은 프록시의 역할 (접근제어, 캐싱)등을 수행하고 원래의 RealSubject에게 일을 다시 넘겨준다.

 

클라이언트를 불러내고 사용해보자!

 

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

위의 테스트는 RealSubject를 캐시 프록시에 DI를 통해서 주입하고 Client가 캐시 프록시를 주입받아서 사용하는 모습을 볼 수있다.

 

데코레이터 패턴

데코레이터 패턴을 보면 프록시 패턴과 다른게?? 무엇인가 싶다.

 

Component란 이름은 이전 프록시 패턴의 Subject인것 같고 특이한점은 바로 Component를 바로 마드는게 아니라 Decorator를 인터페이스로 만들어서 꾸며주는 부분을 영역을 구분한다.

 

저 데코레이터 부분이 없어도 된다. 그렇게하면 프록시 패턴과 매우 유사한 형태를 뛸 것이다.

 

근데 그 모야이 비슷한데.. 어떻게 구분하는 거지? 그것은 의도가 다르다.

 

프록시 패턴은 접근 제어 , 데코레이터패턴은 객체에 추가적인 책임(기능)을 동적으로 추가한다.

반응형

'개인공부 > 디자인패턴' 카테고리의 다른 글

Reflection 과 Jdk동적 프록시  (0) 2022.05.16
인터페이스 프록시 VS 클래스 기반 프록시 패턴  (0) 2022.05.15
템플릿 콜백 패턴  (0) 2022.03.28
전략 패턴  (0) 2022.03.28
템플릿 메서드 패턴  (2) 2022.03.28