프록시(Proxy) 패턴: 구조패턴
프록시(Proxy)를 번역하면 대리자, 대변인의 의미를 갖고 있다. 대리자, 대변인은 누군가를 대신해서 그 역할을 수행하는 존재이다. 이는 프로그램에도 똑같이 적용된다. 즉, 프록시에게 어떤 일을 대신 시키는 것이다.
일반적으로 프록시는 다른 무언가와 이어지는 인터페이스의 역할을 하는 클래스이다. 프록시는 어떠한 것(이를테면 네트워크 연결, 메모리 안의 커다란 객체, 파일, 또 복제할 수 없거나 수요가 많은 리소스)과도 인터페이스의 역할을 수행할 수 있다.
일반적으로 사용하는 프록시라는 용어와 디자인 패턴에서 말하는 프록시 패턴을 구분해야 한다.
전자는 윗 설명처럼 클라이언트와 사용 대상 사이에 대리 역할을 맡은 오브젝트를 두는 방법을 의미하지만, 후자는 프록시를 사용하는 방법 중에서 타깃에 대한 접근 방법을 제어하려는 목적을 가진 경우를 가리킨다.
프록시 패턴은 타깃의 기능을 확장하거나 추가하지 않는다. 대신 클라이언트가 타깃에 접근하는 방식을 변경해준다. 타깃 오브젝트를 생성하기가 복잡하거나 당장 필요하지 않는 경우, 하지만 클라이언트에게 타깃에 대한 레퍼런스를 넘겨야 할 경우, 실제 타깃 오브젝트를 만드는 대신 프록시를 넘겨주는 것이다.
읽기 전용만 필요한 경우, 타깃 오브젝트의 프록시를 만들어 특정 메소드에 접근할 수 없도록 접근권한을 제어할 수도 있다. add()나 remove()를 사용하려는 경우 Exceptrion 예외를 발생하게 만들어주는 것이다.
Client가 어떤 요청을 하면 Proxy가 대신 DoAction()메서드 호출을 하고, 그 반환 값을 전달한다.
프록시 패턴의 장단점
장점
- 기존 객체를 수정하지 않고 일련의 로직을 프록시 패턴을 통해 추가할 수 있다.
- 실제 객체를 수행하기 이전에 전처리를 하거나, 기존 객체를 캐싱할 수 있다.
- 기존 객체의 리소스가 무거울 경우, 이러한 캐싱 과정을 통해 부하를 줄일 수 있는 장점이 있다.
- 기존 객체와 클라이언트의 요청 사이에 위치해 있기 때문에 하나의 방패(보안) 역할을 한다.
단점
- 코드의 복잡도가 증가한다.
- 로직이 난해해져 가독성이 떨어질 수 있다.
- 성능이 저하될 수 있다.
- 객체를 생성할 때 한 단계를 거치게 되므로, 빈번한 객체 생성이 필요한 경우
- 객체 생성을 위해 스레드 생성 및 동기화가 구현되어야 하는 경우
프록시패턴의 예시
ExpensiveObject
public interface ExpensiveObject {
void process();
void notUse();
}
ExpensiveObjectImpl
public class ExpensiveObjectImpl implements ExpensiveObject {
public ExpensiveObjectImpl() {
heavyInitialConfiguration();
}
@Override
public void process() {
System.out.println("processing complete.");
}
@Override
public void notUse() {
System.out.println("not use.");
}
private void heavyInitialConfiguration() {
System.out.println("Loading initial configuration..");
}
}
ExpensiveObjectProxy
public class ExpensiveObjectProxy implements ExpensiveObject {
private static ExpensiveObject object;
@Override
public void process() {
if (object == null) {
object = new ExpensiveObjectImpl();
}
object.process();
}
@Override
public void notUse() {
throw new UnsupportedOperationException();
}
}
ProxyClient
public class ProxyClient {
public static void main(String[] args) {
ExpensiveObject object = new ExpensiveObjectProxy();
object.process();
object.process();
object.notUse();
}
}
//출력
Loading initial configuration..
processing complete.
processing complete.
Exception in thread "main" java.lang.UnsupportedOperationException
at XX.week8.proxy.ExpensiveObjectProxy.notUse(ExpensiveObjectProxy.java:16)
at XX.week8.proxy.ProxyClient.main(ProxyClient.java:9)
Reference
https://dev-coco.tistory.com/177
https://github.com/eugenp/tutorials/tree/master/patterns-modules/design-patterns-structural/src
'OOP > Design Pattern' 카테고리의 다른 글
14. 인터프리터(Interpreter) 패턴 (0) | 2023.02.21 |
---|---|
13. 커맨드(Command) 패턴 (0) | 2023.02.20 |
11. 플라이웨이트(Flyweight) 패턴 (0) | 2023.02.20 |
10. 퍼사드(Facade) 패턴 (0) | 2023.02.20 |
09. 데코레이터(Decorator) 패턴 (0) | 2023.02.14 |