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
	}
}

우리가 하려는 것은 ExampleServicelogic()이라는 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를 만들어서 시간을 측정할 수 있었다.


굳이…? 이렇게까지 하는 이유가 뭐냐. 어떤 점이 좋아진거냐

일단 코드를 불필요하게 적었다가 다시 지우는 일이 없어졌고, 지우는 과정에 있어서 실수로 안지우게 되는 일도 없어졌다. DefaultExampleServiceclass는 logic()method만 구현하면 되고, ProxyExampleServiceclass는 추가적인 기능을 구현하는 것에만 집중하면 된다. 따라서 본인이 집중해야핳 한 가지에만 일에만 집중할 수 있다는게 장점이다.

그 외에는,


extends keyword로 상속을 해서 구현할 수도 있지만, 상속은 1개 class밖에 못하고, 그마저도 finalkeyword로 class가 구현됐다면 상속이 불가능하다. 따라서 간단하게 테스트 할 것이 아니라면, interface를 구현해서 Proxy pattern을 구현하는게 좋다고 생각한다.


Dynamic Proxy

Java reflection을 사용하여 run-time시에도 객체를 생성할 수 있다. Spring AOP에도 쓰인다. 나중에 Spring에 대해 자세히 공부할 때 다시 다뤄보도록 하겠다.


Reference

GoF 디자인 패턴 - 인프런 백기선 강사님