프록시 패턴은 어떤 객체에대한 접근을 제어하기 위해 대리자(Proxy) 객체를 사용하는 디자인 패턴이다.
즉, 클라이언트가 실제 객체를 직접 접근하지않고 프록시(대리인)를 통해 접근하도록 만든다.
Subject (인터페이스 또는 추상클래스)
Real Subject (실제 객체)
Proxy(프록시 객체)
Real Subject와 동일한 인터페이스를 구현하고, 클라이언트의 요청을 실제 객체로 전달하면서 부가적인 기능을 수행.// 공통 인터페이스
public interface Image {
void display();
}
// 실제 이미지 클래스 (이미지를 로드하고 출력)
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImage(); // 생성 시 이미지 로드 (비싼 작업)
}
private void loadImage() {
System.out.println(filename + " 이미지를 로딩 중...");
}
@Override
public void display() {
System.out.println(filename + " 이미지를 화면에 표시합니다.");
}
}
// 프록시 클래스 (실제 이미지의 로딩을 지연시키는 역할)
public class ProxyImage implements Image {
private String filename;
private RealImage realImage; // 실제 객체 참조
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename); // 실제 객체를 필요할 때만 생성 (Lazy Loading)
}
realImage.display();
}
}
public class ProxyPatternExample {
public static void main(String[] args) {
Image image1 = new ProxyImage("photo1.jpg");
Image image2 = new ProxyImage("photo2.jpg");
// 실제 이미지를 로드하지 않고 프록시만 생성됨
System.out.println("\n=== 첫 번째 이미지 호출 ===");
image1.display(); // 여기서만 RealImage 생성 및 로딩
System.out.println("\n=== 첫 번째 이미지 다시 호출 ===");
image1.display(); // 이미 로드된 이미지 사용 (캐싱 효과)
System.out.println("\n=== 두 번째 이미지 호출 ===");
image2.display(); // 두 번째 이미지 로딩
}
}
ProxyImage예제가 대표적public class ProtectionProxy implements Image {
private RealImage realImage;
private String filename;
private boolean hasPermission;
public ProtectionProxy(String filename, boolean hasPermission) {
this.filename = filename;
this.hasPermission = hasPermission;
}
@Override
public void display() {
if (!hasPermission) {
System.out.println("접근이 거부되었습니다.");
return;
}
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
public class CachedImageProxy implements Image {
private String filename;
private RealImage realImage;
private boolean isLoaded = false;
public CachedImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (!isLoaded) {
realImage = new RealImage(filename);
isLoaded = true;
}
realImage.display();
}
}
// 원격 서버에서 동작하는 객체를 프록시로 대체
public interface RemoteService extends java.rmi.Remote {
String getData() throws java.rmi.RemoteException;
}