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

目录
  • 前言
  • 使用场景
  • 代码分析
  • 总结

前言

设计模式在我看来更像是一种设计思维或设计思想,它就像《孙子兵法》一样,为你的项目工程提供方向,让你的项目工程更加健壮、灵活,延续生命力。本文即将分享的是设计模式的其中一种:代理模式。

代理模式

通用官方定义:代理模式(Proxy Pattern) 是一种结构型设计模式,通过代理对象控制对原对象的访问,并允许在访问前或访问后做一些处理。

简单理解就是给一个对象找了一个替代品,这个替代品得到原对象授权,可以拦截一些无效或低效的访问,从而使得原对象可以释放时间做自己的事情。这样替代品实现了自己价值,原对象也得到了解放,两全其美的选择!!

代理主要分为以下几种类型

  • 静态代理:仅用于单个接口实现类,程序运行前已经存在。调用时需要传入具体实例,调用方可以直接获取具体实例。
  • 动态代理:可以服务多个接口实现类,可以在程序运行时,通过反射机制动态创建代理对象。

使用场景

既然这么说了,那就结合实际介绍几个,还不是轻松拿捏~

场景一:作为一个气血方刚的男青年,汽车总是绕不开的话题,那就先以汽车为例。

4s店或汽车厂家均可以出售汽车,对于购车消费者来说,可以直接去喜欢的汽车店去体验成品,不必跋山涉水的跨省或跨市去汽车厂家。有了4S店代理,可以节省消费者时间,更快体验到心仪的汽车,最终也是通过汽车厂家拿到成品;同时汽车工厂通过这些代理,可以更快售出汽车,可谓是一举两得。关系类图如下:

场景二:上面讲述的是静态代理的案例,再来一个最近实践的动态代理需求场景。

人力业务平台接入了不同客户,同时为了满足客户不同的接入需求,采用动态代理模式会为每个客户动态生成代理对象,比如需要提取客户A的简历数据,根据客户A的标识获取代理类并执行对应的实现逻辑,从而获取客户A的数据信息。关系如下

代码分析

结合上述动态代理业务场景,按照UML类型进行代码设计,来演示下整体过程。首先将数据提取接口(IHandlerService)抽象出来,同时提供一个通用实现(HandlerServiceImpl)。

/*
 * 通用接口
 * */
public interface IHandlerService {

    /*
     * 抽取数据
     * */
    void handle();

    /**
     * 打印内容
     *
     * @param content 输出内容
     */
    String print(String content);

    /**
     * 设置信息
     *
     * @param prefix 信息前缀
     */
    void setPrefix(String prefix);
}

/*
 * 通用实现
 * */
@Service
public class HandlerServiceImpl implements IHandlerService {

    /*
     * 默认信息前缀
     * */
    private String prefix = "default";

    @Override
    public void handle() {
        System.out.println("=======自定义实现类" + prefix + "======");
    }

    @Override
    public String print(String content) {
        System.out.println(prefix + " 实现类输出 -》" + content);
        return prefix + "success";
    }

    @Override
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
}

接下来创建个代理类,变量包含通用接口,也可以增加业务所需的其它变量。(java动态代理核心内容:InvocationHandler接口和Proxy类,代理对象在执行函数时,会通过InvocationHandler接口的invoke调用执行函数)具体代码如下

public class MultiDynamicProxy implements InvocationHandler {

    /**
     * @see InvocationHandler
     * 每个代理实例的调用处理程序必须实现的接口,当通过代理实例调用方法时,
     * 这个方法的调用会被转发至实现InvocationHandle接口类的invoke方法去执行
     */
    private static Map<String, IHandlerService> map = new HashMap<>();
    public static String key = "default";

    private void addElements(String key) {
        if (map.containsKey(key)) return;
        IHandlerService handlerService = new HandlerServiceImpl();
        handlerService.setPrefix(key);
        map.put(key, handlerService);
    }

    public static IHandlerService newInstance(IHandlerService handlerService) {
        MultiDynamicProxy handlerProxy = new MultiDynamicProxy(handlerService);
        // 抽象逻辑接口
        Class<IHandlerService> handlerServiceClass = IHandlerService.class;

        /**
         *  param1:指定接口(interface)的类加载器,用于装入定义的代理类
         *  param2:动态代理类要实现的接口
         *  param3:将执行的代理方法调用派发给代理类(程序)
         * */
        return (IHandlerService) Proxy.newProxyInstance(handlerServiceClass.getClassLoader(),
                new Class[]{handlerServiceClass}, handlerProxy);
    }

    public MultiDynamicProxy(IHandlerService handlerService) {
        map.put(key, handlerService);
    }

    /*
     * 自定义实现类对象替换代理类对象,并执行
     * param1:proxy 方法被调用的代理实例,即真实的代理对象
     * param2:method 代理对象的method对象
     * param3:args 代理对象方法传递的参数
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("=====代理类执行====" + proxy.getClass().getSimpleName());
        Object invoke = method.invoke(getElement(), args);
        return invoke;
    }

    private IHandlerService getElement() {
        if (null == map.get(key)) {
            addElements(key);
        }
        return map.get(key);
    }

小编在每个环节都增加了日志输出,就很容易理解每个环节都做了哪些处理,日志内容请接着往下看

public static void main(String[] args) {
        IHandlerService handlerService = MultiDynamicProxy.newInstance(new HandlerServiceImpl());
        String s = handlerService.print("客户A");
        System.out.printf("执行结果 => " + s);
    }
    // 输出结果
    // =====代理类执行====$Proxy0
    // default 实现类输出 -》客户A
    // 执行结果 => defaultsuccess

观察结果可以看出,执行的service实例确实为代理对象($Proxy0),后续可以动态接入客户实现,并注册到客户信息集合,当然,也可以对实现类进行扩展,但考虑到通用性,所以接口职责尽可能保持单一,避免业务交叉,造成后续的维护困难。

总结

以上就是本文所分享的全部内容,静态代理部分由于相对比较简单,就没写代码,主要是动态代理,理解上比较容易,但是具体的执行过程确实需要仔细分析,才能明白其实现原理。

代理模式确实对于目标对象有保护作用,也方便了目标对象的扩展,但凡事都有两面性,它也不是完美的,由于多了代理层,请求处理增加处理过程,进而会降低响应速度,同时也增加了系统复杂性,维护成本会有些增加。

没有最完美的设计模式,只有最适合业务场景的设计模式。

以上就是Java躲不过设计模式的坑之代理模式详解的详细内容,更多关于Java代理模式的资料请关注我们其它相关文章!

(0)

相关推荐

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

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

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

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

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

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

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

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

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

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

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

    目录 代理模式 分类 主要角色 作用 静态代理与动态代理的区别 静态代理的基本使用 创建抽象主题 创建真实主题 创建代理主题 客户端调用 JDK动态代理的基本使用 创建抽象主题 创建真实主题 创建代理主题 客户端调用 小优化 CGLIB动态代理的基本使用 创建抽象主题 创建真实主题 创建代理主题 客户端调用 小优化 CGLIB与JDK动态代理区别 1.执行条件 2.实现机制 3.性能 代理模式 代理模式(Proxy Pattern)属于结构型模式. 它是指为其他对象提供一种代理以控制对这个对象的

  • Java设计模式--代理模式

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

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

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

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

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

  • Java中的代理模式详解及实例代码

    java 代理模式详解 前言: 在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为"代理"的第三者来实现间接引用.代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务. 简单来说代理模式就是通过一个代理对象去访问一个实际对象,并且可以像装饰模式一样给对象添加一些功能. 静态代理 所谓静态代理即在程序运行前代理类就已经存在,也就是说我们编写代码的时候就已经把代理类的代码写好了,而动态代理则

  • JavaScript 设计模式中的代理模式详解

    前言: 代理模式,代理(proxy)是一个对象,它可以用来控制对另一个对象的访问. 现在页面上有一个香港回归最想听的金典曲目列表: <ul id="container"> <li>我的中国心</li> <li>东方之珠</li> <li>香港别来无恙</li> <li>偏偏喜欢你</li> <li>相亲相爱</li> </ul> 需要给页面添加

  • 深入理解JavaScript系列(31):设计模式之代理模式详解

    介绍 代理,顾名思义就是帮助别人做事,GoF对代理模式的定义如下: 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 代理模式使得代理对象控制具体对象的引用.代理几乎可以是任何对象:文件,资源,内存中的对象,或者是一些难以复制的东西. 正文 我们来举一个简单的例子,假如dudu要送酸奶小妹玫瑰花,却不知道她的联系方式或者不好意思,想委托大叔去送这些玫瑰,那大叔就是个代理(其实挺好的,可以扣几朵给媳妇),那我们如何来做呢? 复制代码 代码如下: // 先声明美女对象 var

  • java代理模式与动态代理模式详解

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 生活中的例子:过年加班比较忙,没空去买火车票,这时可以打个电话到附近的票务中心,叫他们帮你买张回家的火车票,当然这会附加额外的劳务费.但要清楚票务中心自己并不卖票,只有火车站才真正卖票,票务中心卖给你的票其实是通过火车站实现的.这点很重要!

  • JAVA 静态代理模式详解及实例应用

    JAVA 静态代理模式 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问. 代理模式说白了就是"真实对象"的代表,在访问对象时引入一定程度的间接性,因为这种间接性可以附加多种用途. 在这实现代码之前,先讲一个简单的生活故事,我们都知道我们周边有很多公司有房屋买卖或租赁的业务,比如链家(LianJia),但链家本身是不存在任何实际房屋资产的,他所售卖租赁的房屋均需要房屋产权所有人(HomeMaster)提供,才得以实现公司的房源需求:同时公司要的卖房租房业务均需要公司

  • JavaScript设计模式之代理模式详解

    代理模式是非常常见的模式,比如我们使用的VPN工具,明星的经纪人,都是代理模式的例子.但是,有人会疑问,明明可以直接访问对象,为什么中间还要加一个壳呢?这也就说到了代理模式的好处.在我看来,代理模式最大的好处,就是在不动原有对象的同时,可以给原有对象增加一些新的特性或者行为. /** * pre:代理模式 * 小明追求A,B是A的好朋友,小明比较腼腆,不好意思直接将花交给A, * 于是小明将花交给B,再由B交给A. */ //----------- 示例1 --------- // 不使用代理

  • SpringAop实现原理及代理模式详解

    目录 Spring Aop的原理 1. JDK动态代理 2. CGLIB动态代理 3. Spring项目中如何强制使用CGLIB代理方式 Spring Aop的原理 Spring的AOP就是通过动态代理实现的.当为某个Bean或者某些Bean配置切面时,Spring会为其创建代理对象,当调用该对象的某个方法时,实际是调用生成的代理类的对象方法.Spring的Aop主要是使用了两个动态代理,分别是JDK的动态代理和CGLIB动态代理. 1. JDK动态代理 如果代理类实现了接口,Spring默认会

  • PHP实现设计模式中的抽象工厂模式详解

    抽象工厂模式(Abstact Factory)是一种常见的软件设计模式.该模式为一个产品族提供了统一的创建接口.当需要这个产品族的某一系列的时候,可以为此系列的产品族创建一个 具体的工厂类. [意图] 抽象工厂模式提供一个创建一系统相关或相互依赖对象的接口,而无需指定它们具体的类[GOF95] [抽象工厂模式结构图] [抽象工厂模式中主要角色] 抽象工厂(Abstract Factory)角色:它声明一个创建抽象产品对象的接口.通常以接口或抽象类实现,所有的具体工厂类必须实现这个接口或继承这个类

随机推荐