首页 > 其他分享 >设计模式 -- 代理模式(Proxy Pattern)

设计模式 -- 代理模式(Proxy Pattern)

时间:2024-08-31 11:50:40浏览次数:6  
标签:target -- Pattern Object 代理 接口 目标 对象 设计模式

基本介绍

  1. 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

  2. 被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象

  3. 代理模式有不同的形式, 主要有三种 静态代理动态代理 (JDK 代理、接口代理)和 Cglib 代理 (可以在内存动态的创建对象,而不需要实现接口, 他是属于动态代理的范畴) 。

原理结构图

1 静态代理

1.1 基本介绍

        静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类。

1.2 应用实例

  1. 定义一个接口:ITeacherDao

  2. 目标对象 TeacherDAO 实现接口 ITeacherDAO

  3. 使用静态代理方式,就需要在代理对象 TeacherDAOProxy 中也实现 ITeacherDAO

  4. 调用的时候通过调用代理对象的方法来调用目标对象.

  5. 特别提醒:代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法

1.2.1 类图

1.2.2 代码实现

// 代理对象,静态代理
public class TeacherDaoProxy implements ITeacherDao {
    private ITeacherDao target; //  目标对象,通过接口来聚合

    //  构造器
    public TeacherDaoProxy(ITeacherDao target) {
        this.target = target;
    }

    @Override
    public void teach() {
        System.out.println("开始代理	完成某些操作。。。。。 ");//  方法
        target.teach();
        System.out.println("提交。。。。。");//  方法

    }
}

1.3 静态代理优缺点

  1. 优点:在不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展

  2. 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类

  3. 一旦接口增加方法,目标对象与代理对象都要维护

2 动态代理

2.1 基本介绍

  1. 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理

  2. 代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象

  3. 动态代理也叫做:JDK 代理、接口代理

2.2 JDK 中生成代理对象的API

  1. 代理类所在包:  java.lang.reflect.Proxy

  2. JDK 实现代理只需要使用 newProxyInstance 方法,但是该方法需要接收三个参数,完整的写法是: static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)

2.3 应用实例

2.3.1 类图

2.3.2 代码实现

public class Client {

    public static void main(String[] args) {
        //  TODO Auto-generated method stub
        //  创建目标对象
        ITeacherDao target = new TeacherDao();

        //  给目标对象,创建代理对象, 可以转成 ITeacherDao

        ITeacherDao proxyInstance = 
            (ITeacherDao) new ProxyFactory(target).getProxyInstance();

        //  proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
        System.out.println("proxyInstance=" + proxyInstance.getClass());

        //  通过代理对象,调用目标对象的方法
        //  proxyInstance.teach();

        proxyInstance.sayHello(" tom ");
    }

}

public class ProxyFactory {

    //  维护一个目标对象 , Object 
    private Object target;

    //  构造器 , 对 target 进行初始化
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //  给目标对象 生成一个代理对象
    public Object getProxyInstance() {
        //  说明
        /*
         * public static Object newProxyInstance(ClassLoader loader,
         * Class<?>[] interfaces, InvocationHandler h)
         * 
         * 1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
         * 2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
         * 3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
         * 
         */
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(), 
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy,
                                     Method method, 
                                     Object[] args) throws Throwable {
                    System.out.println("JDK 代理开始~~");
                    //  反射机制调用目标对象的方法
                    Object returnVal = method.invoke(target, args);
                    System.out.println("JDK 代理提交");
                    return returnVal;
                }
            });
    }

}

3 Cglib 代理

3.1 基本介绍

  1. 静态代理和JDK 代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理,这就是 Cglib 代理

  2. Cglib 代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将Cglib 代理归属到动态代理。

  3. Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口.它广泛的被许多 AOP 的框架使用,例如 Spring AOP,实现方法拦截

  4. 在 AOP 编程中如何选择代理模式:目标对象需要实现接口,用 JDK 代理;目标对象不需要实现接口,用 Cglib 代理。

     5. Cglib 包的底层是通过使用字节码处理框架 ASM 来转换字节码并生成新的类

 4 常见的几种代理模式介绍

4.1 防火墙代理

        内网通过代理穿透防火墙,实现对公网的访问。

4.2 缓存代理

        比如:当请求图片文件等资源时,先到缓存代理取,如果取到资源则 ok,如果取不到资源,再到公网或者数据库取,然后缓存。

4.3 远程代理

        远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息。在分布式系统中,远程代理被用于处理不同地址空间中的通信。例如,客户端可以通过远程代理与服务器端的服务进行交互,而无需直接与实际的服务对象通信。这简化了网络通信的复杂性,并提供了更好的性能和安全性。

4.4 同步代理

        主要使用在多线程编程中,完成多线程间同步工作

4.5 结构代理

        在面向切面编程(AOP)中,代理模式是实现关注点分离的重要手段。通过代理对象,可以在不改变原始对象代码的情况下,添加或修改功能,例如日志、安全、事务管理等。这极大地提高了代码的可重用性和模块化。

5 优缺点

5.1 优点

  1. 松耦合性:代理模式可以将目标对象与代理对象解耦,使得它们可以独立地进行修改和扩展。
  2. 安全性增强:代理对象可以保护目标对象,隐藏其真实实现细节,提高系统的安全性。
  3. 访问控制:代理对象可以控制对目标对象的访问,如权限验证、日志记录等,增加了系统的灵活性和功能扩展性。
  4. AOP支持:代理模式是实现面向切面编程(AOP)的重要方式,广泛应用于事务管理、日志记录、性能监控等方面。

5.2 缺点

  1. 复杂性增加:引入代理模式会增加代码的复杂性,特别是在使用动态代理时,需要理解和处理动态生成的代理类。
  2. 性能考虑:虽然代理模式可以提供许多便利,但在客户端和目标对象之间增加一个代理对象可能会导致请求处理速度变慢。
  3. 维护成本增加:由于代理模式涉及更多的类和交互,可能会增加系统的整体维护成本。

6 总结

        综上所述,代理模式是一种结构型设计模式,旨在通过提供一个中间层来控制和增强对象访问。代理对象充当客户端和目标对象之间的中介,可以在将请求发送给目标对象之前或之后执行附加操作。适用于多种场景,但需谨慎考虑其复杂性和性能影响。

标签:target,--,Pattern,Object,代理,接口,目标,对象,设计模式
From: https://blog.csdn.net/qq_67342067/article/details/141683041

相关文章

  • 设计模式 -- 享元模式(Flyweight Pattern)
    1问题引出        小型的外包项目,给客户A做一个产品展示网站,客户A的朋友感觉效果不错,也希望做这样的产品展示网站,但是要求都有些不同:有客户要求以新闻的形式发布有客户人要求以博客的形式发布有客户希望以微信公众号的形式发布直接复制粘贴一份,然后根据......
  • 【机器学习】sklearn核心分类算法比较
    sklearn核心分类算法比较sklearn分类问题的核心算法及其关联核心分类算法其他分类算法算法之间的关联示例代码运行结果sklearn分类问题的核心算法及其关联在scikit-learn中,分类问题是机器学习中最常见的任务之一。scikit-learn提供了多种分类算......
  • 在Ubuntu系统上使用Docker部署.NET 6程序
    基础用法1.安装Docker首先,确保你的Ubuntu系统上安装了Docker。可以通过以下命令安装Docker:sudoaptupdatesudoaptinstalldocker.io安装完成后,启动Docker并设置为开机自启:sudosystemctlstartdockersudosystemctlenabledocker 2.创建.NET6应用程序如果你......
  • 05.函数和递归
    5.函数和递归inlinefunctions---内联函数functiontemplate---函数模板5.1C++中的程序构件functionprototype---函数原型5.1.1函数原型Afunctionprototypeisadeclarationofafunctionthattellsthecompilerthefunction’sname,itsreturntypeand......
  • 内存管理-32-系统内存统计-4-/proc/vmstat
    基于msm-5.4一、打印内容1.打印格式#cat/proc/vmstat/*1.打印全局数组vm_zone_stat[]的值,enumzone_stat_item描述各条目*/nr_free_pages617775nr_zone_inactive_anon16518nr_zone_active_anon979541nr_zone_inactive_file698879nr_zone_active_file17223......
  • 常用背包dp模板(未完待续)
    部分板子优化中...你好哇,我是flypig114代码里有各部分及变量数组的注释,so...不多废话,直接上正题!01背包无优化#include<bits/stdc++.h>usingnamespacestd;#definellint//为了方便修改类型constllN=1000;//辅助定义数组lln,m;//n是背包容量m是物品数量llv[N],......
  • Session的运行机制
    浏览器通过web访问服务器,服务器的web服务开启后,第一步就是开启session,这也是session的第一阶段:session_start()这个函数的作用:开启session,然后根据以前设置的session_name去读取cookie信息,判断$_Cookies[$session_name]判断是否有值,也就是是否存在session_id,如果存在就用......
  • 06.类-数组(array)和string
    6.类-数组(array)和string6.1数组数组是一组连续的内存位置,它们都具有相同的类型。为了指代数组中的特定位置或元素,我们指定数组的名称和特定元素在数组中的位置编号。数组名称遵循与其他变量名相同的约定。下标必须是整数或整数表达式,带下标的数组名是一个左值,它可以在赋值......
  • CS专业科研论文绘图,及演示动画可用的工具
      1、2D绘图演示图:PowerPoint,Keynote, Visio,位图:AdobePhotoshop, 矢量图:Illustrator,CorelDRAW 排版:Indesign 2、3D建模3D模型:3dsMax,Rhino, 3、动画演示2D、3D动画:Canva(类ppt), Maya,C4D,AdobeAnimate,AdobeAfterEffects,KeyShot,Blender,ToonBoomHarmony......
  • 自我介绍+软工5问
    这个作业属于哪个课程软件工程这个作业要求在哪里作业要求这个作业的目标<在博客园发一篇随笔,介绍你自己,提出5个你想弄懂的问题以及想收获些什么,并在github中写下自己的介绍>介绍自己大家好,我是22级计科4班学生林丙昆。兴趣爱好是打球,各式各样的球,还喜欢音乐,尤......