새소식

반응형
기타

[디자인 패턴] Proxy 패턴

  • -
반응형

Proxy

Proxy 는 단어 뜻대로 대리, 대리인이라는 뜻을 가지고 있습니다.

대리, 대리인은 누군가를 대신해서 그 역할을 수행하는 존재입니다. Proxy 패턴에서도 Proxy 라는 단어에 맞게

어떤 일을 수행할 때 대신 전달하거나 처리하는 역할을 합니다.

 

Proxy 패턴

출처 : https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%ED%8C%A8%ED%84%B4

위 Proxy 패턴 이미지를 보면은 DoAction() 메서드를 가지고 있는 Subject 라는 인터페이스가 존재합니다.

Subject 인터페이스를 구현하는 클래스는 RealSubject 와 Proxy 2개의 클래스입니다.

클라이언트가 Subject 인터페이스를 구현한 RealSubject 클래스의 DoAction() 메서드를 호출하면

Proxy 라는 클래스가 대신 RealSubject 의 DoAction() 메서드를 호출하고 반환값을 클라이언트에게 전달한다.

 

즉, 정리하면 아래와 같다.

1. DoAction() 메서드를 가지고 있는 Subject 인터페이스가 존재한다.

2. Subject 인터페이스를 구현한 클래스는 RealSubject 와 Proxy 가 있다.

3. 클라이언트는 RealSubject 클래스의 DoAction() 메서드를 호출한다.

4. 클라이언트의 요청을 Proxy 클래스가 대신해서 RealSubject 클래스의 DoAction() 을 호출한다.

5. 호출한 Proxy 클래스는 반환값을 받아 클라이언트에게 전달한다.

 

이렇게 꼭 Proxy 클래스가 존재해야 하는 이유는 RealSubject 클래스는 본연의 필수적인 역할만 수행하도록 하고

또 다른 역할을 부여하지 않는다. (단일 책임의 원칙, SRP)

 

단일 책임의 원칙(Single Responsibility Principle)
"어떤 클래스를 변경해야 하는 이유는 오직 하나 뿐이어야 한다." -로버트 C. 마틴
클래스에 역할과 책임을 너무 많이 주지 마라는 뜻이다.

어떤 특정 클래스에 모든 기능을 넣기 보다는 목적과 취지에 맞는 속성과 메서드를 잘 분리해서
여러 클래스에 넣어야 한다.

 

위키백과에 있는 자바 코드를 가져와서 살펴보자

import java.util.*;

interface Image {
    public void displayImage();
}

//on System A
class RealImage implements Image {
    private String filename;
    public RealImage(String filename) {
        this.filename = filename;
        loadImageFromDisk();
    }

    private void loadImageFromDisk() {
        System.out.println("Loading   " + filename);
    }

    @Override
    public void displayImage() {
        System.out.println("Displaying " + filename);
    }
}

//on System B
class ProxyImage implements Image {
    private String filename;
    private Image image;

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    @Override
    public void displayImage() {
        if (image == null)
           image = new RealImage(filename);

        image.displayImage();
    }
}

class ProxyExample {
    public static void main(String[] args) {
        Image image1 = new ProxyImage("HiRes_10MB_Photo1");
        Image image2 = new ProxyImage("HiRes_10MB_Photo2");

        image1.displayImage(); // loading necessary
        image2.displayImage(); // loading necessary
    }
}

 

Image 라는 인터페이스가 있고 해당 인터페이스를 구현한 RealImage 클래스와 ProxyIamge 클래스가 있다.

RealImage 클래스는 생성될 때 생성자 함수에 의해 filename 을 한번 출력하고 구현 메서드를 호출하면

또 한번 출력된다.

ProxyImage 클래스는 구현 메서드인 displayImage 에서 RealImage를 생성하고 RealImage 클래스의 

구현메서드인 displayImage() 메서드를 호출한다.

 

이제 main 에서 ProxyImage 클래스를 2개 생성하고 호출하게 되면 아래와 같이 RealImage 클래스에서 호출한

filename 들이 출력된다.

//출력 결과
Loading    HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Loading    HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2

위와 같이 RealImage 클래스는 filename 이라는 변수명만 출력하는 본연의 역할만 수행하고

ProxyImage 클래스는 클라이언트의 요청을 받아 파일명을 넘기면 대신해서 RealImage 를 호출하여

로직을 대신 수행하게 됩니다.

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.