티스토리 뷰

1. 프록시 패턴이란?

특정 객체에 대한 접근을 제어하기 위한 용도로 대리인이나 대변인에 해당하는 객체를 제공하는 패턴.

 

구성요소

1) Proxy

- 프록시 객체가 RealSubject에 대해 접근할 수 있도록 참조를 갖는다.

- RealSubject와 Subject 인터페이스가 동일하다면 프록시는 Subject에 대한 참조를 할 수 있다.

- RealSubject에 대한 접근을 제어하며, 생성/참조에 대한 권한을 가질 수 있다.

 

2) Subject

- RealSubject와 Proxy의 공통 인터페이스이며, RealSubject가 필요한 곳에 Proxy를 통해 사용할 수 있도록 한다.

 

3) RealSubject

- 프록시가 대신하는 실제 객체를 정의한다.

 

프록시의 종류

1) Remote Proxy: 요청과 그에 대한 argument를 인코딩하고 Real Subject의 실제 주소에게 전달하는 것을 담당한다.

2) Virtual Proxy: Real Subject에 대한 캐싱을 제공한다.

3) Protection Proxy: 요청에 대한 권한 체크를 프록시가 대신 수행해준다.

 

2. 동기

장점

1) 기존 코드를 변경하지 않고 새로운 기능을 추가할 수 있다.

2) 기존 코드가 해야하는 일만 유지할 수 있다.

3) 기능 추가 및 초기화 지연 등으로 다양하게 활용할 수 있다.

 

단점

1) 코드의 복잡도가 증가한다.

 

3. 구현

구현 시 고려사항

1) 프록시 객체가 꼭 RealSubject의 타입을 몰라도 된다.

- 만약 프록시의 클래스가 하나의 추상 인터페이스를 통해 RealSubject의 모든 것을 수행해도 되는 상황이라면 굳이 RealSubject 마다 Proxy를 하나하나 만들 필요가 없다.

- 모든 RealSubject를 감싸는 프록시를 만들면된다.

- 하지만 만약 Proxy가 여러 RealSubject 객체들을 생성해줘야 된다면 (virtual 처럼) 각 클래스 타입을 알아야 한다.

 

예시 코드

다음과 같은 코드가 있다고 가정한다.

public class Client {

    public static void main(String[] args) throws InterruptedException {
        GameService gameService = new GameService();
        gameService.startGame();
    }
}

public class GameService {
    public void startGame() {
        System.out.println("이 자리에 오신 여러분을 진심으로 환영합니다.");
    }
}

 

public interface GameService {
    void startGame();
}

public class GameServiceProxy implements GameService {
    private GameService gameService;
    @Override
    public void startGame() {
        long before = System.currentTimeMillis();
        if (this.gameService == null) {
            this.gameService = new DefaultGameService();
        }
        gameService.startGame();
        System.out.println(System.currentTimeMillis() - before);
    }
}

public class DefaultGameService implements GameService {

    @Override
    public void startGame() {
        System.out.println("이 자리에 오신 여러분을 진심으로 환영합니다.");
    }
}

public class Client {

    public static void main(String[] args) {
        GameService gameService = new GameServiceProxy();
        gameService.startGame();
    }
}