Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

낭비를 없애기 - Proxy Pattern 본문

Java/디자인 패턴

낭비를 없애기 - Proxy Pattern

Seung__ 2021. 11. 15. 23:45

1.Proxy Pattern


  • 객체에 대한 접근을 제어하기 위해 대리자를 둔다.

 

 

2. 의도와 동기


  • 어떤 객체가 생성에 초기화 비용이 많이 들거나 복잡한 경우 간단한 처리는 대리자를 통해 하게된다.
  • 실제적으로 비용이 많이 들어가는 처리일 때 객체를 만들도록 한다.

 

3. 객체 종류


  • 원격지 프록시(remote proxy) : 서로 다른 주소 공간에 존재하는 객체를 대리하는 로컬 객체
  • 가상 프록시(virtual proxy): 고비용의 객체는 필요한 경우만 생성
  • 보호용 프록시(protextion proxy) : 실제 객체에 대한 접근  권한을 제어하기 위한 경우 사용.

 

4. 객체 협력 (collaborations)


  • Proxy
    • 실제 참조할 대상을 관리
    • 실제 객체와 동일한 메서드 제공
    • 클라이언트에게 먼저 노출되는 객체
  • RealSubject
    • 프록시가 대리하는 실제 객체
  • Subject
    • Proxy와 Real의 공통 메서드 선언

 

 

5. 중요한 결론 (consequence)


  • 프록시 패턴은 객체에 접근하는데 보호, 가상등의 역할을 한다.

 

 

 

6. 예제


  • 주어진 string을 출력하는 프린터 클래스가 있다.
  • 프린터 인스턴스 생성에는 5초가 소요된다.
  • PrinterProxy는 print()를 호출 시점에 Printer 인스턴스가 없으면 Printer 인스턴스를 생성한다.
  • 나머지 메서드는 Printer 인스턴스가 없어도 proxy에서 처리함.
public interface Printable {

    public String getPrinterName();
    public void setPrinterName(String name) ;
    public void print(String string);
}
  • 프린터 인스턴스 생성에 5초가 걸린다.
public class Printer implements Printable{

    String name;

    public Printer() {
       heavyJob("Printer 인스턴스 생성 중...");
    }

    public Printer(String name) {
        this.name = name;
        heavyJob("Printer 인스턴스 생성 중...");
    }

    private void heavyJob(String message) {
        System.out.println(message);
        for (int i=0; i<5; i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(".");
        }
        System.out.println("complete");
    }


    @Override
    public String getPrinterName() {
        //나는 진짜 object다..
        System.out.println("real : getName()");
        return name;
    }

    @Override
    public void setPrinterName(String name) {
        System.out.println("real : setName()");
        this.name = name;
    }


    @Override
    public void print(String string) {
        System.out.println("==== "+ name+ " ====");
        System.out.println(string);
    }
}
  • PrinterProxy는 Printer객체 앞에서 Printer 객체 대신에 몇몇 기능을 대신한다.
    • 다만 Print()메서드는 진짜 Printer 객체에서 처리할 수 있기 때문에, 해당 메서드 호출 시점에 Printer 인스턴스가 없으면 새로 생성한다. 
  • 프린터 인스턴스 생성에 5초가 걸린다.
    • 따라서 realize() 진행 중 다른 Thread에서 Printer resource에 접근하지 못하도록 막음.
public class PrinterProxy implements Printable{

    private String name;
    private Printer real; //real object

    public PrinterProxy() {
    }

    public PrinterProxy(String name) {
        this.name = name;
    }


    @Override
    public String getPrinterName() {
        System.out.println("proxy : getName()");
        return name;
    }

    @Override
    public void setPrinterName(String name) {
        if (real != null){
            real.setPrinterName(name);
        }
        else {
            System.out.println("proxy : setName()");
            this.name = name;
        }

    }

    @Override
    public void print(String string) {
        realize();
        real.print(string);
    }

    //5초 지연을 줄건데, 그 동안에 interrupt 들어오면 안됨! 멈춰!
    public synchronized void realize() {
        if (real == null){
            real  = new Printer(name);
        }
    }


}
public class Main {

    public static void main(String[] args) {

        Printable p = new PrinterProxy("Alice");
        System.out.println("현재의 이름은 " + p.getPrinterName() + " 입니다.");
        p.setPrinterName("Bob");
        p.print("test~");

        p.print("hello~");
        p.setPrinterName("tomas");
        p.print("world");
    }
}
proxy : getName()
현재의 이름은 Alice 입니다.
proxy : setName()
Printer 인스턴스 생성 중...
.
.
.
.
.
complete
==== Bob ====
test~
==== Bob ====
hello~
real : setName()
==== tomas ====
world
  • 이처럼 client입장에서 proxy인지 real object인지 모르고 사용하기 때문에 proxy객체를 통해,
  • 자원이 많이 소모되는 인스턴스 생성을 최대한 늦출 수 있는 장점이 있고,
  • real object 앞에서 real object 처럼 사용되기 때문에 real object에 대한 보호 기능도 할 수 있다.

 

7. GitHub : 211115 proxy pattern


 

GitHub - bsh6463/designPattern

Contribute to bsh6463/designPattern development by creating an account on GitHub.

github.com

 

Comments