프록시 패턴

정선호·2023년 5월 24일
0

Design Patterns

목록 보기
18/24

관련 문서

프록시 패턴

위키피디아 - 프록시 패턴
설명 및 스도코드

  • 다른 객체에 대한 대체 또는 자리표시자를 제공할 수 있는 구조 디자인 패턴
    • 일반적으로 프록시는 다른 무언가와 이어지는 인터페이스의 역할을 하는 클래스
    • 프록시는 원래 객체에 대한 접근을 제어하므로, 사용자의 요청이 원래 객체에 전달되기 전 또는 후에 무언가를 수행할 수 있도록 한다

프록시 패턴의 구조

  • 서비스 인터페이스(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();
    }
}
profile
학습한 내용을 빠르게 다시 찾기 위한 저장소

0개의 댓글