관련 문서
프록시 패턴
위키피디아 - 프록시 패턴
설명 및 스도코드
- 다른 객체에 대한 대체 또는 자리표시자를 제공할 수 있는 구조 디자인 패턴
- 일반적으로 프록시는 다른 무언가와 이어지는 인터페이스의 역할을 하는 클래스
- 프록시는 원래 객체에 대한 접근을 제어하므로, 사용자의 요청이 원래 객체에 전달되기 전 또는 후에 무언가를 수행할 수 있도록 한다
프록시 패턴의 구조
- 서비스 인터페이스(Service Interface)
- 서비스의 인터페이스 선언
- 프록시가 서비스 객체로 위장할 수 있으려면 해당 인터페이스를 따라야 함
- 서비스(Service)
- 프록시(Proxy)
- 서비스 객체를 가리키는 참조 필드를 갖고 있음
- 프록시가 요청의 처리 완료시 그 처리된 요청을 서비스 객체에 전달
- 일반적으로 프록시들은 서비스 객체들의 전체 수명 주기 관리
- 클라이언트(Client)
- 같은 인터페이스를 통해 서비스들 및 프록시들과 함께 작동해야 한다. 그러면 서비스 객체를 기대하는 모든 코드에 프록시를 전달할 수 있기 때문이다
프록시 패턴의 적용
- 어쩌다 필요한 무거운 서비스 객체가 항상 가동되어 있어 시스템 자원들을 낭비할 때 지연된 초기화(가상 프록시)를 위해
- 특정 클라이언트들만 서비스 객체를 사용할 수 있도록 하려는 경우에 접근 제어(보호 프록시)를 위해
- 원격 서비스의 로컬 실행(원격 프록시). 서비스 객체가 원격 서버에 있는 경우
- 요청들의 로깅(로깅 프록시). 서비스 객체에 대한 요청들의 기록을 유지하려는 경우
- 요청 결과들의 캐싱(캐싱 프록시), 클라이언트 요청들의 결과들을 캐시하고 이 캐시들의 수명 주기를 관리해야 할 때, 특히 결과들이 상당히 큰 경우에 사용
- 스마트 참조. 사용하는 클라이언트들이 없어 거대한 객체를 해제할 수 있어야 할 때 사용
다른 패턴과의 관계
- 어댑터는 다른 인터페이스를, 프록시는 같은 인터페이스를, 데코레이터는 향상된 인터페이스를 래핑된 객체에 제공한다
- 퍼사드 패턴은 복잡한 객체 또는 시스템을 보호하고 자체적으로 초기화한다는 점에서 프록시와 유사합니다. 퍼사드 패턴과 달리 프록시는 자신의 서비스 객체와 같은 인터페이스를 가지므로 이들은 서로 상호 교환이 가능하다.
- 데코레이터와 프록시의 구조는 비슷하나 이들의 의도는 매우 다르다. 두 패턴 모두 한 객체가 일부 작업을 다른 객체에 위임해야 하는 합성 원칙을 기반으로 한다. 이 두 패턴의 차이점은 프록시는 일반적으로 자체적으로 자신의 서비스 객체의 수명 주기를 관리하는 반면 데코레이터의 합성은 항상 클라이언트에 의해 제어된다는 점이다.
프록시 패턴 예제
public interface Image {
void displayImage();
}
public class Real_Image implements Image {
private String fileName;
public Real_Image(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
private void loadFromDisk(String fileName) {
System.out.println("Loading " + fileName);
}
@Override
public void displayImage() {
System.out.println("Displaying " + fileName);
}
}
public class Proxy_Image implements Image {
private Real_Image realImage;
private String fileName;
public Proxy_Image(String fileName) {
this.fileName = fileName;
}
@Override
public void displayImage() {
if (realImage == null) {
realImage = new Real_Image(fileName);
}
realImage.displayImage();
}
}
public class Proxy_Main {
public static void main(String[] args) {
Image image1 = new Proxy_Image("test1.png");
Image image2 = new Proxy_Image("test2.png");
image1.displayImage();
System.out.println();
image2.displayImage();
}
}