Java结构型设计模式中代理模式示例详解

目录
  • 代理模式
    • 分类
    • 主要角色
    • 作用
    • 静态代理与动态代理的区别
  • 静态代理的基本使用
    • 创建抽象主题
    • 创建真实主题
    • 创建代理主题
    • 客户端调用
  • JDK动态代理的基本使用
    • 创建抽象主题
    • 创建真实主题
    • 创建代理主题
    • 客户端调用
    • 小优化
  • CGLIB动态代理的基本使用
    • 创建抽象主题
    • 创建真实主题
    • 创建代理主题
    • 客户端调用
    • 小优化
  • CGLIB与JDK动态代理区别
    • 1.执行条件
    • 2.实现机制
    • 3.性能

代理模式

代理模式(Proxy Pattern)属于结构型模式。

它是指为其他对象提供一种代理以控制对这个对象的访问。

在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

在代理模式中,创建具有现有对象的对象,以便向外界提供功能接口。

想在访问一个类时做一些控制的时候就可以是用代理模式。

分类

代理模式属于结构型模式,分为静态代理和动态代理。

1.静态代理:静态定义代理类

静态代理需要自己生成代理类

2.动态代理:动态生成代理类

动态代理不用亲自去实现,通常使用现成的API即可。目前普遍使用的是JDK自带的代理与CGLIB提供的类库。

主要角色

代理模式一般包含三种角色:

1.抽象主题角色(Subject)

抽象主题类的主要职责是声明真实主题与代理的共同接口方法,该类可以是接口也可以是抽象类

2.真实主题角色(RealSubject)

该类也被称为被代理类,该类定义了代理所表示的真实对象,是负责执行系统真正的罗辑业务对象

3.代理主题角色(Proxy)

代理主题也被称为代理类,其内部特有RealSubject的引用,因此具备完全的对RealSubject的代理权。

客户端调用代理对象的方法,同时也调用被代理对象的方法,但是会在代理对象前后增加一些处理代码。可以理解为代码增强,实际上就是在原代码罗辑前后增加一些代码逻辑,而使调用者无感知。

作用

1.保护目标对象,将代理对象与真实被调用目标对象分离

2.增强目标对象

3.降低系统耦合性,提升扩展性

静态代理与动态代理的区别

1.静态代理只能通过手动完成代理操作,如果被代理类增加了新的方法,代理类需要同步增加,违背开闭原则。

2.动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原测。

3.若动态代理要对目标类的增强逻辑进行扩展,结合策略模式,只需要新增策略类便可完成,无须修改代理类的代码。

静态代理的基本使用

静态代理需要自己生成代理类

创建抽象主题

public interface ISubject {
    /**
     * 买票
     */
    void buyTickets();
}

创建真实主题

public class RealSubject implements ISubject {
    public void buyTickets() {
        System.out.println("进行买票操作");
    }
}

创建代理主题

public class Proxy implements ISubject {
    private ISubject subject;
    public Proxy(ISubject subject) {
        this.subject = subject;
    }
    public void buyTickets() {
        before();
        subject.buyTickets();
        after();
    }
    public void before() {
        System.out.println("买票前的操作");
    }
    public void after() {
        System.out.println("买票后的操作");
    }
}

客户端调用

    public static void main(String[] args) {
        Proxy proxy = new Proxy(new RealSubject());
        proxy.buyTickets();
    }

买票前的操作
进行买票操作
买票后的操作

JDK动态代理的基本使用

创建抽象主题

public interface IUser {
    /**
     * 购物
     */
    void shopping();
}

创建真实主题

public class User implements IUser{
    @Override
    public void shopping() {
        System.out.println("user shopping....");
    }
}

创建代理主题

public class JDKProxy implements InvocationHandler {
    private Object tarjet;
    public JDKProxy(Object tarjet) {
        this.tarjet = tarjet;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理user,执行shopping()开始...");
        Object oj = method.invoke(tarjet, args);
        System.out.println("代理user,执行shopping()结束...");
        return oj;
    }
}

客户端调用

    public static void main(String[] args) {
        User user = new User();
        JDKProxy jdkProxy = new JDKProxy(user);
        IUser proxyInstance = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), jdkProxy);
        proxyInstance.shopping();
    }

代理user,执行shopping()开始...
user shopping....
代理user,执行shopping()结束...

小优化

在调用时候,传入了一推参数,可进一步优化

public class JDKProxy implements InvocationHandler {
    private Object tarjet;
    public Object JDKProxy(Object target){
        this.tarjet = target;
        Class<?> clazz =  target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理user,执行shopping()开始...");
        Object oj = method.invoke(tarjet, args);
        System.out.println("代理user,执行shopping()结束...");
        return oj;
    }
}
    public static void main(String[] args) {
        JDKProxy jdkProxy = new JDKProxy();
        IUser user= (IUser)jdkProxy.JDKProxy(new User());
        user.shopping();
    }

CGLIB动态代理的基本使用

CGLIB动态代理也不需要生成代理类,实现MethodInterceptor 就可以了。

注意:CGLib不能代理final的方法

创建抽象主题

注意:CGLb代理的目标对象不需要实现任何接口,就可以通过动态继承目标对象实现动态代理。所以此处可以不用创建接口。直接使用真实主题。

public interface IUser {
    public void shopping();
}

创建真实主题

public class User implements IUser{
    @Override
    public void shopping() {
        System.out.println("user shopping....");
    }
}

直接使用真实主题。

public class User {
    public void shopping() {
        System.out.println("user shopping....");
    }
}

创建代理主题

public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理user,执行shopping()开始...");
        Object invokeSuper = methodProxy.invokeSuper(o, objects);
        System.out.println("代理user,执行shopping()结束...");
        return invokeSuper;
    }
}

客户端调用

    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(User.class);
        enhancer.setCallback(cglibProxy);
        IUser iUser = (IUser) enhancer.create();
        iUser.shopping();
    }

小优化

在客户端调用时,稍显复杂,可进一步优化

public class CglibProxy implements MethodInterceptor {
    public Object getInstance(Class<?> clazz) throws Exception{
        //相当于Proxy,代理工具类
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理user,执行shopping()开始...");
        Object invokeSuper = methodProxy.invokeSuper(o, objects);
        System.out.println("代理user,执行shopping()结束...");
        return invokeSuper;
    }
}
    public static void main(String[] args) throws Exception {
        IUser user = (IUser) new CglibProxy().getInstance(User.class);
        user.shopping();
    }

CGLIB与JDK动态代理区别

1.执行条件

JDK动态代理实现了被代理对象的接口。CGLb代理的目标对象不需要实现任何接口,它是通过动态继承目标对象实现动态代理。

2.实现机制

JDK动态代理调用代理方法是由Java内部的反射机制来实现的,需要读取接口信息。CGLib动态代理是通过FastClass机制来实现的,需要覆盖父类方法。

3.性能

首先都在运行期生成字节码。

JDK动态代理的代理逻辑简单,直接写Class字节码,使用反射机制在生成类的过程中比较高效。

CGLib代理实现更复杂,使用ASM框架写Class字节码,但是asm在生成类之后的相关执行过程中比较高效。但是可以通过将asm生成的类进行缓存,解决asm生成类过程低效问题。

一句话:CGLib生成代理类比JDK动态代理效率低,但是执行效率比JDK动态代理高。

到此这篇关于Java结构型设计模式中代理模式示例详解的文章就介绍到这了,更多相关Java代理模式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-09-21

Java设计模式之代理模式详解

一.代理模式 代理模式就是有一个张三,别人都没有办法找到他,只有他的秘书可以找到他.那其他人想和张三交互,只能通过他的秘书来进行转达交互.这个秘书就是代理者,他代理张三. 再看看另一个例子:卖房子 卖房子的步骤: 1.找买家 2.谈价钱 3.签合同 4.和房产局签订一些乱七八糟转让协议 一般卖家只在签合同的时候可能出面一下,其他的1,2,4都由中介去做.那你问这样有什么用呢? 首先,一个中介可以代理多个卖房子的卖家,其次,我们可以在不修改卖家的代码的情况下,给他实现房子加价.打广告等等夹带私货的

深入理解Java设计模式之代理模式

目录 一.引言 二.什么是代理模式 三.代理模式的结构 四.代理模式和装饰模式的异同 五.代理模式和委托 六.代理模式的种类 七.代理模式的应用场景 八.代理模式的优缺点 九.代理模式的实现 总结 一.引言 我们都知道,数据库连接是很珍贵的资源,频繁的开关数据库连接是非常浪费服务器的CPU资源以及内存的,所以我们一般都是使用数据库连接池来解决这一问题,即创造一堆等待被使用的连接,等到用的时候就从池里取一个,不用了再放回去,数据库连接在整个应用启动期间,几乎是不关闭的,除非是超过了最大闲置时间.

Java设计模式之代理模式详细解读

目录 Java设计模式-代理模式 什么是代理模式? 代理模式-UML图: 源代码: 运行结果: 总结: 应用实例: 优点: 缺点: 使用场景: Java设计模式-代理模式 什么是代理模式? 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 所谓的代理严格来讲就是两个子类共同实现一个接口,其中一个子类负责真实业务实现,另一个辅助完成主类业务逻辑操作. 代理模式-UML图: 源

Java设计模式--代理模式

目录 1.代码设计的代理模式 2.计算机网络中的正向代理和反向代理 总结 1.代码设计的代理模式 代理模式属于构建型模式(Proxy),提供了对目标对象的一种访问方式; 即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法. 主要思想: 由被代理对象(业务类)和代理类组成,代理类通常包括日志代理类.权限代理类. 转载:ht

Java躲不过设计模式的坑之代理模式详解

目录 前言 使用场景 代码分析 总结 前言 设计模式在我看来更像是一种设计思维或设计思想,它就像<孙子兵法>一样,为你的项目工程提供方向,让你的项目工程更加健壮.灵活,延续生命力.本文即将分享的是设计模式的其中一种:代理模式. 代理模式 通用官方定义:代理模式(Proxy Pattern) 是一种结构型设计模式,通过代理对象控制对原对象的访问,并允许在访问前或访问后做一些处理. 简单理解就是给一个对象找了一个替代品,这个替代品得到原对象授权,可以拦截一些无效或低效的访问,从而使得原对象可以释放

Java设计模式以虹猫蓝兔的故事讲解代理模式

目录 什么是代理模式 优点 缺点 知识点 代理模式实现 卖酒 干娘的酒馆 大奔的酒摊 测试 总结 模式: 代理模式 案例: 大奔代干娘卖酒 什么是代理模式 代理模式的定义: 由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 优点 1.代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用: 2.代理对象可以扩展目标对象的功能: 3.代理模式能将客户端与目标对象分离,在一定程度上降低了系统

Java通俗易懂系列设计模式之代理模式

前言 国内程序员好像普遍对百度都没好感,而且百度近些年产生了不少负面的新闻,像16年的魏则西事件,近期的导演吴京黑白照事件,以及最近作家六六斥百度李彦宏:"你是做搜索引擎还是骗子首领",还有一件就是与程序员有关的:搜索Julia语言,在百度和Google得出首条搜索结果的差异性而被吐槽.Google虽然受欢迎,但是在国内因内容审查问题未解决而不能使用,如果我们要使用它就必须使用代理服务器,由于放置代理服务器的地区区域可以访问google,所以我们可以先访问代理服务器,通过代理服务器转发

浅谈JAVA设计模式之代理模式

代理模式 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 介绍 意图: 为其他对象提供一种代理以控制对这个对象的访问. 主要解决: 在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时

浅谈C#设计模式之代理模式

代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口.根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理.远程代理.虚拟代理.缓冲代理等,它们应用于不同的场合,满足用户的不同需求 复制代码 代码如下: using System; using System.Collections.Generic; using System.Linq; using

浅谈JAVA设计模式之享元模式

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象.我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式.由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象. 介绍 意图: 运用共享技术有效地支持大量细粒度的对象. 主要解决: 在有大量

浅谈Java反射与代理

Java反射机制与动态代理,使得Java更加强大,Spring核心概念IoC.AOP就是通过反射机制与动态代理实现的. 1 Java反射 示例: User user = new User(); user.setTime5Flag("test"); Class<?> cls = Class.forName("com.test.User"); //接口必须public,无论是否在本类内部使用!或者使用cls.getDeclaredMethod(),或者遍历修

Java设计模式之代理模式与装饰模式实例详解

本文实例讲述了Java设计模式之代理模式与装饰模式.分享给大家供大家参考,具体如下: 之所以把这两种模式放在一起说,是因为我发现这了两种模式几乎一模一样! 从网上也搜了一些资料,发现两者还是有一些区别的.我们在学习的同时也把这种困惑搞清楚. 定义: 代理模式,为其他对象提供一种代理以控制对这个对象的访问. 装饰模式,动态地给一个对象添加一些额外的职责. 代理模式,很好理解,就是把一个对象再次封装,以后就对封装的对象访问就可以了. 因为代理对象已经取代了被代理对象. 装饰模式,给一个对象增加功能,

java设计模式—静态代理模式(聚合与继承方式对比)

一.概述 1.目标:要在Tank的move()方法做时间代理及日志代理(可以设想以后还要增加很多代理处理),且代理间的顺序可活更换 2.思路: (1)聚合:代理类聚合了被代理类,且代理类及被代理类都实现了movable接口,则可实现灵活多变,具体看代码 (2)继承:继承不够灵活,随着功能需求增多,继承体系会非常臃肿.具体看代码 二.代码 1.Movable.java 2.Tank.java 3.TankTimeProxy.java 4.TankLogProxy.java 5.Tank2Time.

Java设计模式之代理模式原理及实现代码分享

简介 Java编程的目标是实现现实不能完成的,优化现实能够完成的,是一种虚拟技术.生活中的方方面面都可以虚拟到代码中.代理模式所讲的就是现实生活中的这么一个概念:中介. 代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用. 代理模式包含如下角色: ISubject:抽象主题角色,是一个接口.该接口是对象和它的代理共用的接口. RealSubject:真实主题角色,是实现抽象主题接口的类. Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实

详解JAVA设计模式之代理模式

什么是设计模式(Design Pattern)? 设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结. 代理模式的定义? 代理模式就是为其他对象提供一种代理,以控制对这个对象的访问. 代理对象起到中介作用,可去掉功能服务或增加额外的服务. 代理对象和目标对象的关系? 代理对象:增强后的对象 目标对象:被增强的对象 他们不是绝对的,会根据情况发生变化. 代理模式的两种实现方式? 1.静态代理:代理和被代理对象在代理之前是确定的,它们都实现相同的接口或者继承相同的抽象类. 2

浅谈Java设计模式系列-装饰器模式

一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是单方,和代理模式相同,而且目标必须是抽象的. 而实际上,装饰器模式和代理模式的实现方式基本一致,只在目标的存在上有些差别,这个后面我们具体讲述. 二.初步分析 上面提到了两点: 涉及的是单方 目标是抽象的 我们来想一下,所谓单方主要指的是在整个装饰器模式中不存在双方调用,要解决的也不是双方调用的问题,而是解决单方提供对外服务的问题,这个单方在自行对外提供服务时,功能不足,或

Java设计模式之代理模式(Proxy模式)介绍

理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理. 设计模式中定义:为其他对象提供一种代理以控制对这个对象的访问. 为什么要使用代理模式 1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive论坛系统中,就使用Proxy进