본문 바로가기
Java

java - 프록시 패턴(구조 패턴)

by sinabeuro 2021. 8. 23.
728x90

프록시 패턴

Proxy는 대리인이라는 뜻으로써, 무언가를 대신해서 처리하는 것입니다.

프록시 패턴은 Proxy Class를 통해서 대신 전달하는 형태로 설계되며, 실제 Client는 Proxy로부터 결과를 받습니다.

다시말하자면, 어떤 객체를 사용하고자 할때, 객체를 직접적으로 참조하는 것이 아닌 대리인 객체(Proxy) 통해 제어 흐름이 됩니다.

여기서 대리인 객체(Proxy) 다른 무언가와 이어지는 인터페이스의 역할을 하는 클래스입니다.

이 때 Proxy Class는 제어 흐름만 할 뿐 결과값을 조작하거나 변경시키면 안됩니다.

 

프록시 패턴은 Cache의 기능으로도 활용 가능합니다.

SOLID  중에서 개방폐쇄 원칙(OCP)과 의존역전원칙(DIP)를 따릅니다.

프록시 패턴 다이어그램

프록시 패턴의 장점

- 원래 객체에 접근에 대해 사전처리를 할 수 있습니다.

 

프록시 패턴의 단점

- 객체를 생성할 때 한 단계를 거치게 되므로, 빈번한 객체 생성이 필요한 경우 성능이 저하될 수 있습니다.

- 프록시 내부에서 객체 생성을 위해 스레드가 생성, 동기화가 구현되어야 하는 경우 성능이 저하될 수 있습니다.

- 로직이 난해해져 가독성이 떨어질 수 있습니다.

 

 

프록시 패턴 구현 예제1

// Html.java
public class Html {
    private String url;

    public Html(String url){
        this.url = url;
    }
}

위의 Html 클래스는 RealSubject 에 해당되면 본래의 경우,

인터페이스를 상속받아 구현하지만, 프록시 패턴의 대상이 되면 인터페이스의 메소드를 직접적으로 구현하지 않아도 됩니다.

// IBrowser.java
public interface IBrowser {
    Html show();
}

프록시 패턴과 프록시 객체(Proxy Class)를 사용하기 위해서 꼭 인터페이스가 필요합니다!

 

// BrowserProxy.java
public class BrowserProxy implements IBrowser {

    private String url;
    private Html html;

    public BrowserProxy(String url){
        this.url = url;
    }

    @Override
    public Html show() {
        if(html == null){
            this.html = new Html(url);
            System.out.println("BrowserProxy loading html from "+url);
        }
        System.out.println("BrowserProxy use cache html");
        return html;
    }
}

Proxy Class(중계 클래스)로 사용할 BrowserProxy 클래스에 IBrowser 인터페이스를 상속받고 메소드를 오버라이드를 통해서 실제 서비스와 같은 메서드를 구현합니다. 

 

처음 show 메소드를 호출 시에는 인스턴스 객체를 생성합니다.

이후 show 메소드를 호출하면 캐시와 같은 함수 코드가 실행됩니다.

 

// main.java
 
import com.company.design.adapter.Electronic110V;
import com.company.design.proxy.BrowserProxy;
import com.company.design.proxy.IBrowser;

public class Main {

    public static void main(String[] args) {

        IBrowser browser = new BrowserProxy("www.naver.com");
        browser.show();
        browser.show();
        browser.show();
        browser.show();

    }
}

browser.show() 매소드 호출 시 처음만 인스턴스 객체가 만들어집니다.

이후에는 캐시 내용들이 출력됩니다.

main.java 실행 결과

 


프록시 패턴 구현 예제2

프로시 패턴을 사용해서 여러 객체 접근에 따른 AOP 사전처리를 구현해보았습니다.

// IBrowser.java
public interface IBrowser {
    Html show();
}​

 

// AopBrowser.java
public class AopBrowser implements IBrowser {

    private String url;
    private Html html;
    private Runnable before;
    private Runnable after;

    public AopBrowser(String url, Runnable before, Runnable after) {
        this.url = url;
        this.before = before;
        this.after = after;
    }

    @Override
    public Html show() {
        before.run();

        if(html == null) {
            this.html = new Html(url);
            System.out.println("AopBrowser html loading from : "+ url);

            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        after.run();

        System.out.println("AopBrowser html cache : "+ url);
        return html;
    }
}

 

public class Main {

    public static void main(String[] args) {

        AtomicLong start = new AtomicLong();
        AtomicLong end = new AtomicLong();

        IBrowser aopBrowser = new AopBrowser(
                "www.naver.com",
                ()->{
                    System.out.println("before");
                    start.set(System.currentTimeMillis());
                },
                ()->{
                    long now = System.currentTimeMillis();
                    end.set(now - start.get());
                }
        );

        aopBrowser.show();
        System.out.println("loading time : "+end.get());
        aopBrowser.show();
        System.out.println("loading time : "+end.get());

    }
}

 

 

 

 

Thread 클래스와 Runnable 인터페이스 참고 

https://any-ting.tistory.com/36

 

[Java] Thread 클래스와 Runnable 인터페이스 개념 및 사용법

package Access; //사람 스래드 public class Person extends Thread { @Override public void run() { for (int i=0; i< 10; i++){ System.out.println("Sub Thread 일 시작: "+ i); } } } - 지난 시간 안녕하세..

any-ting.tistory.com

 

 

 

728x90

댓글