클라이언트 코드가 곧바로 타겟 객체의 메소드를 호출하는 것이 아니라 프록시 객체를 통해서 타겟 객체의 메소드를 호출하는 것이다. 프록시는 대리인이라는 뜻인데 대리인을 통해서 요청을 하는 구조라고 할 수 있다. 프록시 패턴을 사용해서 타겟 객체의 메소드를 호출하기 전에 추가적인 로직을 수행할 수 있는데 캐싱, 로깅, 지연 로딩, 접근 제어 등을 예로 들 수 있다.
프록시 객체는 외부에서 타겟 객체를 주입받고, 추가적으로 로직을 수행한 뒤 타겟 객체가 본연의 로직을 수행하도록 위임하는 형태를 띈다. 클라이언트 코드는 인터페이스에만 의존하도록 함으로써 실제 구현 객체가 프록시 객체인지 타겟 객체인지 알 수 없도록한다. Workout 인터페이스를 구현하는 타겟 객체 역할을 하는BasicWorkout 과 프록시 객체 역할을 하는 ProxyWorkout 객체가 있다고 가정하자. 클라이언트는 외부에서 주입받은 인터페이스 구현 객체의 workout() 메소드를 호출한다.
interface Workout {
void workout();
}
class BasicWorkout implements Workout {
@Override
public void workout() {
System.out.println("본격적인 운동을 한다.");
}
}
class ProxyWorkout implements Workout {
private final Workout workout;
public ProxyWorkout(Workout workout) {
this.workout = workout;
}
@Override
public void workout() {
System.out.println("준비운동을한다.");
workout.workout();
}
}
class Person {
private final Workout workout;
public Person(Workout workout) {
this.workout = workout;
}
public void workout(){
workout.workout();
}
}
class Example {
public static void main(String[] args) {
Person person = new Person(new ProxyWorkout(new BasicWorkout()));
person.workout();
}
}
[출력 결과]
준비운동을한다.
본격적인 운동을 한다.