代理模式

Posted EthanPark

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理模式相关的知识,希望对你有一定的参考价值。

本人最常用的模式是装饰模式,一直搞不太清楚其跟代理模式的区别,今天来区分一下。

代理模式

代理模式是结构设计模式之一,也是非常好理解的一种模式。根据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包就使用了代理模式,有兴趣的人可以参考源码。

以上是关于代理模式的主要内容,如果未能解决你的问题,请参考以下文章

代理模式

适配器模式和代理模式的区别

新闻代理模式的名词解释是

模式的秘密-适配器模式和代理模式的区别

系统架构设计——设计模式之代理模式CGLIB动态代理实现

什么不是扁平化模式相较于代理模式的劣势