ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] 프록시(Proxy) 패턴
    CSE/Design Pattern 2015. 6. 13. 10:37

    Pattern #10  프록시 패턴





     시간이 많이 소요되는 불필요한 복잡한 객체를 생성하는 시간을 간단한 객체로 줄임







     패턴 요약 

      - 특정 객체에 접근을 조절하기 위하여 대리자(Proxy)를 세움

      - 필요할 때만 비싼 대가의 기능을 접근하도록 프록시를 사이에 둠



     

     동기


      당신이 이번에 참여한 프로젝트는 그래픽을 지원하는 문서편집기를 업그레이드하는 작업이다. 사용자들이 기존의 문서편집기를 사용할 때가장 큰 불만사항은 파일을 여는데 속도가 너무 느리다는 점이다. 이유를 분석해보니 파일을 열 때 문서에 포함된 그림들을 모두 메모리에 올리고, 또 압축된 그림데이터를 Bitmap으로 변환하는 작업을 수행하기 때문이다. 문서의 모든 그림들을 사용자가 보는 경우는 드물다는 점을 이용하여, 사용자가 실제로 보는 그림(화면에 출력을 요구받은 그림 객체) 들만 메모리에 올린다면, 파일 여는 시간을 훨씬 단축 시킬수 있을 것이다. 기존의 설계를 어떻게 변경해야 될까?

       

     





     











     







     해결 방안 

      - 대리자(Proxy)를 내세우기

      - proxy는 기존의 코드에서 image 객체를 대신함

      - proxy는 요청을 받으면, 자신이 대신하고 있는 image객체에 해당 요청을 보냄

      - proxy 객체가 처음 생성될 때는 자신이 대신할 image객체를 미리 만들지 않고, 외부에서 처음 요청이 들어왔을 때(즉, image객체가 필요할 때) image 객체를 생성









      의도 

      - 특정 객체에 대한 접근(access)을 조절하기 위해 대리자를 둔다.


      별명 

      - Surrogate


      적용 범위 

      - remote proxy: 다른 주소에 존재, 다른 공간에 존재하는 객체에 대한 로컬 표현

      - virtual proxy: 복잡한 객체를 필요할 때 생성

      - protection proxy: 원래 객체에 대한 엑세스 권한을 제한

      - smart reference: 객체접근 시 추가적인 액션 수행. 참조횟수를 관리하거나 객체를 수정할 수 없도록 locking



      결과 

      - remote proxy는 객체가 다른 주소공간에 존재하는 사실을 숨길 수 있게 한다.

      - virtual proxy는 객체를 필요할 때 생성하여 최적화를 수행한다.

      - protection proxy와 smart reference는 객체가 접근할 때 추가적인 housekeeping 작업을 수행한다.

      - 불필요한 다운로드 또는 heavy work을 피함.








    예제.




    CommandExecutor.java


     

    1
    2
    3
    4
    5
    6
    7
     
    package proxy;
     
    public interface CommandExecutor {
        public void runCommand(String cmd) throws Exception;
    }
     
    cs



    CommandExecutorImpl.java

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    package proxy;
     
    public class CommandExecutorImpl implements CommandExecutor {
     
        public void runCommand(String cmd) throws Exception {
            Runtime.getRuntime().exec(cmd);
            System.out.println("'" + cmd + "' command executed.");
        }
     
    }
     
    cs





    CommandExecutorProxy.java

     

    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
     
    package proxy;
     
    public class CommandExecutorProxy implements CommandExecutor {
     
        private boolean isAdmin;
        private CommandExecutor executor;
     
        public CommandExecutorProxy(String user, String pwd) {
            if ("Yeon".equals(user) && "Moon".equals(pwd))
                isAdmin = true;
            executor = new CommandExecutorImpl();
        }
     
        public void runCommand(String cmd) throws Exception {
            if (isAdmin) {
                executor.runCommand(cmd);
            } else {
                if (cmd.trim().startsWith("rm")) {
                    throw new Exception(
                            "rm command is not allowed for non-admin users.");
                } else {
                    executor.runCommand(cmd);
                }
            }
        }
     
    }
     
    cs





    ProxyMain.java

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    package proxy;
     
    public class ProxyMain {
        public static void main(String[] args) {
            CommandExecutor executor = new CommandExecutorProxy("Yeon""wrong_pwd");
     
            try {
                executor.runCommand("ls -ltr");
                executor.runCommand(" rm -rf abc.pdf");
            } catch (Exception e) {
                System.out.println("Exception Message:: " + e.getMessage());
            }
        }
    }
     
    cs







     

    댓글

Designed by Tistory.