본문 바로가기

아는 만큼 보인다/Design Pattern

데코레이터 패턴과 프록시 패턴

데코레이터 패턴과 프록시 패턴은 둘 모두가 프록시 오브젝트를 사용한다.

프록시 오브젝트란?

타깃/실체와 같은 인터페이스를 구현한 클래스를 말한다.

전략패턴에서는 같은 인터페이스를 구현한 클래스들은 여러가지 구체적인 기술들을 각각 구현한 클래스들로서  클라이언트에게 여러 기술에 대해 선택의 폭을 확장해 주기 위해서 였다.

그러나 프록시 오브젝트는 전략패턴에서 처럼 또 다른 기술을 구현한 오브젝트가 아니고,

타킷/실체라는 하나의 기술을 사용하면서
그 실체에 부가기능을 더하거나 또는 그 실체로의 접근 방법을 제어하기 위해 구현된다.
결국, 프록시 오브젝트는 타깃/실체의 메소드를 사용한다. 이를 실체에게 위임한다 라고 말한다.



1. 프록시 오브젝트가 부가기능을 더한 것이라면,
데코레이터 패턴이라 부른다.

실례를 들어보자

InputStream os = new BufferedInputStream(new FileInputStream());

InputStream이라는 인터페이스를 구현하 클래스가 두 개 보인다.

둘 중에.. FileInputStream은 타깃/실체이다.

이 실체를 BufferedInputStream이라는 프록시 오브젝트가 감싸안아서 readLine이라는 부가 기능을 더해준다.



2. 프록시 오브젝트가 접근방법을 제어하기 위한 것이라면, 
프록시 패턴이라고 부른다.

두 가지 예가 있다.

하나는, 실체를 늦게 생성하는 예이다.
runtime중 성능상의 문제로 실체/타깃의 생성을 최대한 늦추는게 좋은데, 클라이언트가 실체의 reference를 이른 시점에 원하는 경우, 프록시 오브젝트를 먼저 생성해서 클라이언트에 프록시 오브젝트의 레퍼런스를 주고, 실체에 대한 생성은 runtime중에 프록시 오브젝트가 위임할 실체가 진짜로 필요한 시점에 (즉, 최대한 늦은 시점에) 생성하는 경우다.

두번째는, 접근 권한을 바꾸는 예이다.
실체에 대한 수정자는 public이다. 허나 클라이언트에게 수정 권한을 주기 싫은 경우, 프록시 오브젝트를 중간에 두어 클라이언트가 해당 수정자를 호출하는 경우, 프록시 오브젝트가 UnsupportedOperationException을 throw해주는 경우다.



실체와 프록시 오브젝트들은 동일한 인터페이스를 구현하고 있으며
프록시 오브젝트들도 실체에게 그 핵심 기능을 위임하기 위해 인터페이스를 선언하여 사용한다.
(실체의 구현 클래스를 바로 사용하지 않는다)

그렇기 때문에
하나의 실체에 프록시 오브젝트는 여러 개가 함께 사용될 수 있다
나아가 데코레이션 패턴과 프록시 패턴을 혼합해서 사용할 수 도 있다. 

즉, 프록시 오브젝트가 사용하는 인터페이스의 레퍼런스가 실체/타깃일 수도 있고 아니면 
또다른 프록시 오브젝트일 수 도 있는 것이다.