二十三种设计模式之代理模式(含简单的Java动态代理实现)| 青训营笔记

171 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记,也是我第一次将笔记内容发到平台上,大家请见谅,有错误的地方请指出,我会积极接受批评。

今天阅读了《设计模式的艺术》这本书,这本书写的很好,详略得当,我很喜欢,今天重点看了二十三设计模式之代理模式。

我相信无论大家学习哪个技术最先考虑的就是下面这两个问题,而在这儿里我也是。

1.什么是代理模式?

2.代理模式能够干什么?


1.1 什么是代理模式?

在这本书中,给出了这样一个概念。 代理模式: 给某一个对象提供一个代理,并由代理对象控制对元对象的引用。(代理模式是一种对象结构型模式)。 这样说其实还不是很好理解,简单的来说,代理模式其实就相当于代购公司,你想买一个东西,这个东西在你在的地方买不到,而你把这个钱交给代购公司让代购公司帮你购买。

2.1 结构图

代理模式的结构很简单,核心是代理类!代理模式当中一共有三个角色,分别是真实角色,代理角色,抽象角色。

类似的结构图如图

代理模式.png

2.2 简单代理类伪代码

Class 代理类 extend 抽象类{
    private 真实类 object = new 真实类();

    public void 请求方法前执行方法(){
        具体业务实现…………
    }

    public void 请求方法(){
        请求方法前执行方法();
        object.真实请求方法实现();
        请求方法后执行方法();
    }
    
    public void 请求方法后执行方法(){
        具体业务实现…………
    }
}

这仅仅只是一个简单的伪代码实现,与真实开发有很大差别!

而真正的代理模式根据业务目的分为不同的种类!

2.3常用的代理模式

  • 远程代理

      为一个位于不同的地址空间的对象提供一个本地的代理对象。
      这个不同的地址空间可以在同一台主机中,也可以在另一台主机中。
      远程代理又可以称为大使。
    
  • 虚拟代理

      如果需要创建于给资源消耗较大的对象,先创建一个消耗相对较小的对象来表示
      真实的对象只在需要时才会被真正创建
    
  • 保护代理

      控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限
    
  • 缓冲代理

      为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果
    
  • 智能引用代理

      当一个对象被引用时,提供一些额外的操作,列入将对象被调用的次数记录下来!
    

这里仅仅只是这些常用代理模式的简要说明,一些代理模式的具体实现其实非常复杂!

3.1 Java动态代理

这里实现了一个简单的Java动态代理

//抽象角色
public interface UserDao {

   public boolean findUserById(String userId); 
   
}
//真实角色
public class UserDaoImpl implements UserDao{

    @Override
    public boolean findUserById(String userId) {
        if(userId.equals("亚雷啊")){
            System.out.println("查询"+userId+"用户的信息成功!");
            return true;
        }else{
            System.out.println("查询"+userId+"用户的信息失败!");
            return false;
        }
        
    }
    
}
//自定义请求处理程序
public class LogHandler implements InvocationHandler{
    private Object object;

    //定义无参构造
    public LogHandler() {
    }

    //定义有参构造
    public LogHandler(Object object) {
        this.object = object;
    }

    //实现invoke()方法,
    //这里的逻辑为before() -> 真实方法 -> after()
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object res = method.invoke(object, args);
        after();
        return res;
    }
    public void before(){
        System.out.println("——————————before()方法执行——————————");
    }

    public void after(){
        System.out.println("——————————after()方法执行——————————");
    }
    
}
//客户类
public class Client {
    public static void main(String[] args) {
        InvocationHandler invocationHandler = null;
        UserDao userDao = new UserDaoImpl();
        invocationHandler = new LogHandler(userDao);
        UserDao proxy = null;
        //通过动态代理创建一个代理对象,用于代理UserDao类型的真实角色
        proxy = (UserDao) Proxy.newProxyInstance(
            UserDao.class.getClassLoader(),
             new Class[]{UserDao.class},
              invocationHandler);
        proxy.findUserById("亚雷啊");
        System.out.println("——————————程序结束了——————————");
    }
}

这是程序运行后的结果

     /**
     * ——————————before()方法执行——————————
     * 查询亚雷啊用户的信息成功!
     * ——————————after()方法执行——————————
     * ——————————程序结束了——————————
     */