zoukankan      html  css  js  c++  java
  • 代理模式

    代理模式:为其他对象提供一种代理以控制对这个代理对象的访问

    代理分为两种模式:静态代理、和动态代理模式

    代理模式中有三个角色:

    抽象角色:声明真实对象和代理对象的共同接口。

    代理角色:代理对象与真实对象实现同样的接口,所以它可以在不论什么时刻都可以代理真实对象。代理角色内部包括有对真实对象的引用。所以她可以操作真实对象,同一时候也可以附加其它的操作,相当于对真实对象进行封装。

    真实角色:它代表着真实对象。是我们终于要引用的对象

    静态代理

    模拟场景:

    生活中我们在大城市租房,很多都是中介给介绍的或者二房东,从中介手里可以租到房东的房子,从房东手里也可以租到房子,中介、二房东只是代理房东租房,他们都有一个共同的租房接口。

    租房接口:

    public interface IRent {
        void Rent();//出租
    }
    

    房东出租房子(真实角色):

    public class Host implements  IRent{
        @Override
        public void Rent() {
            System.out.println("房东出租房");
        }
    }
    

    增加一个代理类(代理角色),实现租房的接口

    public class Proxy implements  IRent{
        private Host host;
        public  Proxy(Host host)
        {
            this.host=host;
        }
        @Override
        public void Rent() {
           host.Rent();
        }
    }
    
    public static void main(String[] args) {
        Host host=new Host();
        Proxy proxy=new Proxy(host);
        proxy.Rent();
    }
    

    image-20210609204719909

    现在还是从房东那租房子,只是中间多了一层关系。代理类里面还可以加其他功能,配客户看房吃饭等。

    就是在不改变原有代码的基础上,对原有的代码进行增强,所以才有代理类。

    优点:

    • 一定程度上降低了系统的耦合度,扩展性好。
    • 公共角色交给代理,实现业务的分工
    • 对目标对象的功能增强

    缺点:

    如果要实现多个代理的话,一个真实角色就会产生一个代理角色,开发代码量翻倍

    动态代理

    动态代理和静态代理原理一样,不过动态代理的代理类是自动生成的,不是是手动编写的

    动态代理分为两大类:接口动态代理JDK、类的动态代理cglib、java字节码

    实现JDK动态代理的步骤:

    JDK动态代理中包含一个类和一个接口:

    Proxy类

    Object Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler)
    
    • loader:代理类的入口(当前类的类加载器)
    • interfaces:被代理的接口
    • handler:InvocationHandler接口

    InvocationHandler接口

    public interface InvocationHandler { 
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
    } 
    
    • proxy - 调用该方法的代理实例

    • method - 对应于在代理实例上调用的接口方法的方法实例。

    • args - 包含代理实例上方法调用中传递的参数值的对象数组。

    步骤一:新建一个类,实现代理调用的接口InvocationHandler,并重写里面的invoke方法执行动作

    public class ProxyInvocationHandler implements InvocationHandler {
        //被代理的接口
        private  Object object;
    
        //传入被代理的接口
        public  ProxyInvocationHandler(Object object)
        {
            this.object = object;
        }
        
        //处理代理实例 并返回结果
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
           Object result =method.invoke(object,args);//执行接口  args:接口上的方法
            return result;
        }
    }
    

    步骤二:生成代理类Proxy

    //创建代理对象
    IRent obj=(IRent) Proxy.newProxyInstance(IRent.class.getClassLoader(), new Class<?>[]{IRent.class}, pih);
    

    步骤三:测试

       public static void main(String[] args) {
            //真实对象
            Host host=new Host();
            //代理对象的调用处理程序 并设置要代理的对象
            ProxyInvocationHandler pih=new ProxyInvocationHandler(host);
            //动态生成代理类
            IRent obj=(IRent) Proxy.newProxyInstance(IRent.class.getClassLoader(), new Class<?>[]{IRent.class}, pih);
            obj.Rent();
        }
    

    动态代理的好处

    静态代理有的它都有,静态代理没有的,它也有!

    • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情
    • 公共的业务由代理来完成 . 实现了业务的分工
    • 公共业务发生扩展时变得更加集中和方便
    • 一个动态代理 , 一般代理某一类业务
    • 一个动态代理可以代理多个类,代理的是接口
  • 相关阅读:
    SpringBoot 2.X整合Mybatis
    SpringBoot 2.X集成 jdbc自动配置原理探究
    15 道 Spring Boot 高频面试题,看完直接当面霸【入门实用】
    SpringBoot整合Thymeleaf-基于SpringBoot2.X版本
    vue-manage-system 后台管理系统开发总结
    Node.js 应用:Koa2 使用 JWT 进行鉴权
    Parcel:常见技术栈的集成方式
    HTML5 桌面通知:Notification API
    Electron 实战桌面计算器应用
    Node.js 入门:Express + Mongoose 基础使用
  • 原文地址:https://www.cnblogs.com/cg-ww/p/14869201.html
Copyright © 2011-2022 走看看