웹 페이지의 스크롤을 아래로 내리지 않았는데, 미리 아래 있는 사진을 로드 할 필요는 없다.
그러면 로드하지 않은 자리에는 어떻게 처리해야할까?
사진을 직접 두지 않으려면 대리자를 두는 편이 좋을 것이다.
이러한 경우에 바로 쓰는 것이 'Proxy 패턴'이다.
Proxy는 대리자라는 뜻을 가진 영어 단어로, surrogate라는 이름으로 불리기도 한다.
'Proxy Pattern'이란 특정 기능을 수행하는 객체를 대신하여 접근을 조절하거나 흐름을 제어하는 디자인 패턴이다.
Proxy 패턴은 Subject, Real Subject, Proxy와 같이 구성된다.
이를 이용하는 Client는 Subject를 통하여 subject들을 사용하게 된다.
Subject는 인터페이스로 구성하여 구현이 없는 DoAction과 같은 공통 인터페이스를 선언한다.
RealSubject에서는 이를 상속 받아, 원하는 작업에 대한 코드를 작성한다.
대리자로 호출될 Proxy에서의 DoAction은 아직 RealSubject를 호출하는 경우와 호출하지 않는 경우로 나누어 처리해야한다. 이때, RealSubject를 호출해야하기 때문에 delegate 라고 하는 reference 객체를 갖는다.
1. 리모트 Proxy
다른 주소에 존재하는 객체에 대한 로컬 표현이다. 프록시 클래스는 로컬에, real subject는 remote에 둔다. proxy를 이용하여 원격의 객체를 불러온다고 볼 수 있겠다.
2. 가상 Proxy
게임 캐릭터와 같이 복잡한 객체가 필요할 때 생성한다. 복잡한 객체를 생성하면 비용이 많이 들기 때문에 생성을 미루거나, 이러한 과정을 따로 떼어처리하는 것이다.
3. 보호 Proxy
proxy는 대리자 이외에도 다른 역할을 할 수 있다.
보호 proxy의 경우, 원래 객체에 대한 access 권한을 제어한다.
4. 스마트 레퍼런스
스마트 레퍼런스 역시 추가적인 역할을 한다. 객체에 접근할때 다른 액션을 수행한다. 또한, 참조의 횟수를 관리하고나, 객체를 수정할 수 없도록 로깅한다.
이와 같은 Proxy 패턴을 적용하면 어떠한 장점이 있을까?
proxy 패턴으로 복잡한 객체에 대한 생성을 미룰 수 있다. 또, 접근 제어의 역할도 수행할 수 있는데 이번 예시에서 접근을 제어하는 방법을 알아보자.
쇼핑몰에서 사용자가 계산을 할 때 로그인이 되어 있으면 장바구니 페이지로, 그렇지 않으면 로그인 페이지로 이동하여 비회원은 장바구니로 넘어가지 못하게 된다. 이와 같은 프로그램을 설계해보자.
먼저 User interface를 설계하여 회원과 비회원을 하위 클래스로 갖도록 하였다.
public interface User{
public void checkout();
}
public class Guest implements User{
public void checkout(){
System.out.printlnI("login page");
}
}
public class AuthorizedUser implements User{
public void checkout(){
System.out.println("checkout page");
}
}
Proxy는 이러한 user를 선택하여 생성하도록 한다
public interface UserProxy{
public User getUser();
}
public class UserProxyHandler implements UserProxy{
private boolean isLoggedin ;
UserProxyHandler(boolean isLoggedin){
this.isLoggedin = isLoggedin;
}
public User getUser(){
User user;
if(isLoggedin){
user = new AuthorizedUser();
}else
user = new Guest();
}
return user;
}