Proxy

使用時機

  • 你有一個功能已經實作完成的物件。
  • 因為一些非功能面需求,例如減少記憶體使用、增加操作性能,可想要控制物件的產生、初始化、存取控制等cross-cutting concerns。如果直接修改原本的物件來加入這些控制將會違反基本的物件導向設計原則。
  • 為了達到資訊隱藏,物件的客戶端應該不需要知道物件的內部實作。因此,不管物件是因為需要而及時被產生,或是物件是否位在本地端或是遠端這類的問題,客戶端應該不需要知道。

from: Structural Patterns要解決什麼問題(上)?

from: Proxy Pattern Tutorial with Java Examples

Example

Using proxy pattern for access control

Subject

package com.journaldev.design.proxy;

public interface CommandExecutor {

    public void runCommand(String cmd) throws Exception;
}

Real Subject

package com.journaldev.design.proxy;

import java.io.IOException;

public class CommandExecutorImpl implements CommandExecutor {

    @Override
    public void runCommand(String cmd) throws IOException {
                //some heavy implementation
        Runtime.getRuntime().exec(cmd);
        System.out.println("'" + cmd + "' command executed.");
    }

}

Proxy

package com.journaldev.design.proxy;

public class CommandExecutorProxy implements CommandExecutor {

    private boolean isAdmin;
    private CommandExecutor executor;

    public CommandExecutorProxy(String user, String pwd) {
        if("Pankaj".equals(user) && "J@urnalD$v".equals(pwd))
            isAdmin=true;
        executor = new CommandExecutorImpl();
    }

    @Override
    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);
            }
        }
    }
}

Client

package com.journaldev.design.test;

import com.journaldev.design.proxy.CommandExecutor;
import com.journaldev.design.proxy.CommandExecutorProxy;

public class ProxyPatternTest {

    public static void main(String[] args){
        CommandExecutor executor = new CommandExecutorProxy("Pankaj", "wrong_pwd");
        try {
            executor.runCommand("ls -ltr");
            executor.runCommand(" rm -rf abc.pdf");
        } catch (Exception e) {
            System.out.println("Exception Message::"+e.getMessage());
        }

    }

}

from: Proxy Design Pattern