on
Proxy pattern
Design Pattern 공부
디자인 패턴 공부를 모아놓은 tag 입니다.
Proxy pattern
proxy pattern
: 특정 객체에 대한 접근을 제어하거나 기능을 추가할 수 있는 pattern
Lazy loading, 접근 제어, logging, 캐싱 등 다양하게 응용이 가능하다고 한다.
Static Proxy
Java compile-time에 proxy객체를 생성하여 쓰는 proxy pattern. 쉽게 말해서 Proxy class field에 우리가 쓸 클래스를 미리 선언해놓는 방법으로 쓰기 때문에 이렇게 부른다.
public interface ExampleService {
void logic() throws InterruptedException;
}
먼저 interface를 정의한 다음 우리가 접근할 class를 구현해준다.
public class DefaultExampleService implements ExampleService{
@Override
public void logic() throws InterruptedException {
// logic...
Thread.sleep(1000);
// ...logic
}
}
우리가 하려는 것은 ExampleService
의 logic()
이라는 method의 실행시간을 측정하는 것이다. 하지만 DefaultExampleService
와 같은 구현체 클래스에 코드를 추가하게 되면, 나중에 지워야 하기도 하고 번거롭다. 따라서 우리는 Proxy class를 만들어서 이를 처리해줄 생각이다.
public class ProxyExampleService implements ExampleService {
private final ExampleService exampleService;
public ProxyExampleService(ExampleService exampleService) {
this.exampleService = exampleService;
}
@Override
public void logic() throws InterruptedException {
long start = System.currentTimeMillis();
exampleService.logic(); // ExampleService logic() method
long end = System.currentTimeMillis();
System.out.println("time : " + (end - start));
}
}
이렇게 Proxy class를 만들어서 시간을 측정할 수 있었다.
굳이…? 이렇게까지 하는 이유가 뭐냐. 어떤 점이 좋아진거냐
일단 코드를 불필요하게 적었다가 다시 지우는 일이 없어졌고, 지우는 과정에 있어서 실수로 안지우게 되는 일도 없어졌다. DefaultExampleService
class는 logic()
method만 구현하면 되고, ProxyExampleService
class는 추가적인 기능을 구현하는 것에만 집중하면 된다. 따라서 본인이 집중해야핳 한 가지에만 일에만 집중할 수 있다는게 장점이다.
그 외에는,
- 장점
- 기존 코드를 변경하지 않고 새로운 기능을 추가할 수 있다.
- 기존 코드가 해야 하는 일만 유지할 수 있다.
- 기능 추가 및 lazy initialization 등으로 다양하게 활용이 가능하다.
- 단점
- 코드의 복잡도가 증가한다.
extends
keyword로 상속을 해서 구현할 수도 있지만, 상속은 1개 class밖에 못하고, 그마저도 final
keyword로 class가 구현됐다면 상속이 불가능하다. 따라서 간단하게 테스트 할 것이 아니라면, interface를 구현해서 Proxy pattern을 구현하는게 좋다고 생각한다.
Dynamic Proxy
Java reflection을 사용하여 run-time시에도 객체를 생성할 수 있다. Spring AOP에도 쓰인다. 나중에 Spring에 대해 자세히 공부할 때 다시 다뤄보도록 하겠다.