本人最常用的模式是装饰模式,一直搞不太清楚其跟代理模式的区别,今天来区分一下。
代理模式
代理模式是结构设计模式之一,也是非常好理解的一种模式。根据GoF中所说:
为其他的对象提供代理或者占位符,来控制其访问的权限
从上面的定义就可以知道代理模式的场景主要是当我们需要提供访问访问控制的时候使用的。
假设我们有一个类,要在一个系统上面运行一些命令。在服务器端这个类工作的很正常,但是如果我们想根据这个类做一个客户端程序,那么就会有一些问题。因为基于这个类实现的客户端程序也有相同的权限来删除系统文件或者更改一些你不想让它修改的配置等等。
我们可以通过创建一个代理的类来支持客户端的访问控制。
原执行类
参考如下代码:
package net.ethanpark.design.proxy;
public interface CommandExecutor {
public void runCommand(String cmd) throws Exception;
}
package net.ethanpark.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.");
}
}
上面的代码就是原始的执行类,用来直接在系统上面执行命令用的。
代理类
现在我们可以提供一个功能:只有admin用户才有全部的权限,如果用户不是admin,那么则只能执行部分有限的命令。下面就是简单的代理类实现:
package net.ethanpark.design.proxy;
public class CommandExecutorProxy implements CommandExecutor {
private boolean isAdmin;
private CommandExecutor executor;
public CommandExecutorProxy(User user){
if(user.getUsername().equals("admin"))
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);
}
}
}
}
package net.ethanpark.design.proxy;
public class User {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
测试类
下面是测试类:
package net.ethanpark.design.test;
import net.ethanpark.design.proxy.CommandExecutor;
import net.ethanpark.design.proxy.CommandExecutorProxy;
public class ProxyPatternTest {
public static void main(String[] args){
CommandExecutor executor = new CommandExecutorProxy(new User("notAdmin", "some password"));
try {
executor.runCommand("ls -ltr");
executor.runCommand(" rm -rf abc.pdf");
} catch (Exception e) {
System.out.println("Exception Message::"+e.getMessage());
}
}
}
现在运行测试代码,则输出如下:
'ls -ltr' command executed.
Exception Message::rm command is not allowed for non-admin users.
代理模式通常用来控制访问或者为原有实现提供包裹实现来提高性能。
Java RMI包就使用了代理模式,有兴趣的人可以参考源码。