목차
- ☆ 표시가 붙은 부분은 스터디 중 나온 얘기 혹은 제 개인적인 생각이나 제가 이해한 방식을 적어놓은 것으로, 책에 나오지 않는 내용입니다. 따라서 책에서 말하고자 하는 바와 다를 수 있습니다. 또한 책에는 따로 Step으로 나오지 않습니다. 설명의 편의를 위해 임의로 나눈 것 입니다.
- 모든 이미지의 출처는 헤드퍼스트 디자인패턴 개정판(한빛미디어) 입니다.
프록시 패턴 (Proxy Pattern)
코드 링크 : github
☆ 프록시 패턴의 경우 종류가 다양합니다. 결국 개념은 클라이언트가 실제 객체의 메소드를 호출하면 그 호출을 중간에 가로챈다는 점이고, 그 외 프록시 패턴의 변종들은 그냥 이름 갔다 붙이기 나름인 것 같습니다.
프록시 패턴?
- 특정 객체로의 접근을 제어하는 대리인(특정 객체를 대변하는 객체)을 제공하는 패턴.
- 프록시 패턴을 사용하면 원격 객체라든가 생성하기 힘든 객체, 보안이 중요한 객체와 같은 다른 객체로의 접근을 제어하는 대리인 객체를 만들 수 있습니다.
- 예를들어 원격 프록시의 경우 자바 RMI(☆ 현재로썬 레거시에 RMI 사용된게 있는 경우가 아니라면 쓸 일은 없을 것 같다.) 등을 활용해 원격 객체로의 접근을 제어할 수 있습니다.
- 가상 프록시를 써서 생성하기 힘든 자원으로의 접근을 제어할 수 있습니다.
- 보호 프록시를 써서 접근 권한이 필요한 자원으로의 접근을 제어할 수 있습니다.
- ☆ 그 외 캐시 프록시, 로드 밸런싱 프록시, 인증 프록시 등등 많은 것 같습니다. 뭐 어차피 프록시 패턴이 뭔지만 알면 그 이후론 결국 갔다 붙이기 나름인듯.
- 이하 이미지는 원격 프록시
가상 프록시
- 가상 프록시는 생성하는 데 많은 비용이 드는 객체를 대신합니다. 진짜 객체가 필요한 상황이 오기 전까지 객체의 생성을 미루는 기능을 제공합니다.
- 이하 예시로 짜본 코드 입니다.
public class ProxyTestDrive {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
Subject subject = new Proxy();
subject.print(new BufferedWriter(bw));
}
}
---
public interface Subject {
void print(final BufferedWriter bw) throws IOException;
}
---
public class Proxy implements Subject {
volatile RealSubject realSubject;
Thread retrievealThread;
synchronized void setRealSubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void print(final BufferedWriter bw) throws IOException {
if (realSubject != null) {
realSubject.print(bw);
return;
}
bw.write("I'm Proxy :). wait!\n");
bw.flush();
retrievealThread = new Thread(new Runnable() {
@Override
public void run() {
setRealSubject(new RealSubject());
try {
realSubject.print(bw);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
retrievealThread.start();
}
}
---
public class RealSubject implements Subject {
public RealSubject() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public void print(final BufferedWriter bw) throws IOException {
bw.write("Real Subject!\n");
bw.flush();
}
}
프록시 패턴 변종들의 공통점
- 원격 프록시, 가상 프록시, 보호 프록시 등등의 공통점은 '클라이언트가 실제 객체의 메소드를 호출하면 그 호출을 중간에 가로챈다는 점'
프록시 패턴 vs 데코레이터 패턴
- 용도로 구분 가능.
- ☆ 같은 코드라도 개발자가 이 패턴을 사용한 용도나 목적이 다르다면 이름을 다르게 붙일 수 있을 것 같다. 어쨌든 커뮤니케이션 입장에서 보자면 용도나 목적에 따라 다른 이름을 붙이는게 충분히 의미 있을 것 같다.
- 데코레이터는 클래스에 새로운 행동을 추가하는 용도, 프록시는 어떤 클래스로의 접근을 제어하는 용도.
프록시 패턴 vs 어댑터 패턴
- 어댑터는 다른 객체의 인터페이스를 바꿔 주지만, 프록시는 똑같은 인터페이스를 사용한다는 차이점이 있음.
- 단, 보호 프록시는 어댑터와 비슷하다고 함.
클라이언트가 진짜 객체가 아닌 프록시 객체를 사용하도록 강제하는 법
- 팩토리에서 프록시로 감싼 다음 리턴
- 이 경우 클라이언트는 진짜 객체를 쓰고 있는지, 프록시 객체를 쓰고 있는지 알 수 없음.
'CS > Design Pattern' 카테고리의 다른 글
[디자인 패턴] 전략 패턴 (Strategy Pattern) (0) | 2023.06.17 |
---|---|
자바 싱글톤 패턴의 변화 (다양한 싱글톤 패턴 구현 방법) (0) | 2022.11.15 |
댓글