大话设计模式——5.代理模式(Proxy Pattern)

news2024/11/19 22:40:00
1.定义

为其他具体对象提供一种代理用以控制对这个对象的访问,属于结构型模式。
UML图:
在这里插入图片描述

2.示例

生活中有许多的代理,如房产中介,房主出售的房子挂在中介处,中介帮忙寻找需要的客户,客户不需要直接接触房主。

1)Subject:房子

public interface House {

    /**
     * 卖房子
     */
    void sell();
}

2)RealSubject:将要出售的别墅

public class Villa implements House {

    @Override
    public void sell() {
        System.out.println("房东出售大别墅");
    }
}

3)Proxy:房产中介(静态代理)

public class HouseProxy implements House {

    private Villa villa = new Villa();

    @Override
    public void sell() {
        findCustomers();
        villa.sell();
    }
    
    private void findCustomers() {
        System.out.println("寻找客户");
    }
}

4)client:客户端运行

public class Main {

    public static void main(String[] args) {
        // 无代理
        House villa = new Villa();
        villa.sell();
        System.out.println("----代理----");
        // 有代理
        House villaProxy = new HouseProxy();
        villaProxy.sell();
    }
}

在这里插入图片描述

2.1 采用动态代理

1)JDK动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class JDKHouseProxy implements InvocationHandler {

    // 代理的目标类,运行时进行具体指定
    private Object targetObj;

    public Object newInstance(Object targetObj) {
        // 指定具体的目标类
        this.targetObj = targetObj;

        // 构建目标代理类
        return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(), targetObj.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("实现jdk动态代理 before");

        // 调用目标类方法
        Object result = method.invoke(targetObj, args);

        System.out.println("实现jdk动态代理 after");

        return result;
    }
}

2)CGLib动态代理

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;


public class CGLibHouseProxy implements MethodInterceptor {

    public Object newInstance(Object targetObj) {

        // 创建代理
        Enhancer enhancer = new Enhancer();
        // 设置目标类为父类
        enhancer.setSuperclass(targetObj.getClass());
        // 设置代理类(回调)
        enhancer.setCallback(this);

        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGLib代理 before ");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("CGLib代理 after ");
        return result;
    }
}

3)运行结果

public class Main {

    public static void main(String[] args) {
        // 无代理
        House villa = new Villa();
        villa.sell();
        System.out.println("----代理----");
        // 有代理
        House villaProxy = new HouseProxy();
        villaProxy.sell();

        // jdk动态代理
        System.out.println("----JDK代理----");
        House jdkHouseProxy = (House) new JDKHouseProxy().newInstance(villa);
        jdkHouseProxy.sell();

        // CGLib代理
        System.out.println("----CGLib代理----");
        House cglibHouseProxy = (House)new CGLibHouseProxy().newInstance(villa);
        cglibHouseProxy.sell();
    }
}

在这里插入图片描述

静态代理:由程序或者特定工具生成源代码,在程序编译时已经确定目标类和代理类的关系。容易造成代码冗余,即每个目标类都需要为止创建一个代理类
动态代理:通过java的反射机制在程序运行期间动态的为目标类创建代理类。无需为每个目标类都创建一个代理类,使用更加灵活,具备很好的扩展性

  • JDK代理:目标类需要实现一个接口,为spring默认的代理方式。
  • CGLib代理:有时候目标类是没有实现接口的,那么就采用改方式进行代理。通过在内存中构建目标类的派生类,继承目标类的方法进行改写。采用继承的方式进行代理,因此如果目标类是final类,或者方法是private、static属性
3.总结
  • 无需修改代理的对象源码,符合开闭原则,可使系统具有较好的灵活性和可扩展性
  • 可以对代理的具体对象做增强处理,如增加一些功能等
  • 增加了系统的复杂性与调用过程的链路
4.代理模式 VS 装饰模式
  • 代理模式代理的是具体的对象,可保护目标对象与增强目标对象的功能
  • 装饰模式装饰的是一类对象,可对一类具有共同特点的对象进行控制和处理
  • 装饰模式适合于需要动态地给对象添加新功能的情况,代理模式适合于需要控制对对象访问的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1507451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv9环境搭建推理测试

引子 对于CV从业者来说,YOLO系列是个绕不过的经典结构,笔者遥想当年YOLO横空出世的时候,Faster RCNN还是学术界目标检测的翘楚。二阶段检测还是大行其道,不过时至今日,估摸着没有人再提二阶段目标检测的结构了。YOLO系…

【软件测试面试】银行项目测试面试题+答案(二)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 面试题&#xff1…

ChatGPT+MATLAB应用

MatGPT是一个由chatGPT类支持的MATLAB应用程序,由官方Toshiaki Takeuchi开发,允许您轻松访问OpenAI提供的chatGPT API。作为官方发布的内容,可靠性较高,而且也是完全免费开源的,全程自己配置,无需注册码或用…

【超级干货】播放器核心知识点-音视频同步原理深入剖析

引言 本文是自己学习利用ffmpeg实现音视频同步播放的总结文档,参考了网上一些博客,同时调试ffplay源码进行理解,站在巨人的肩膀上学习,感谢开源和分享精神。文中粘贴的代码每行都有注释,确保读者能理解所涉函数的每一行代码的意义。 章节 因为ffplay源码阅读起来比较复…

TripoSR:开源3D重建模型,0.5秒就能完成2D到3D图转换

TripoSR是由Tripo AI和Stability AI合作开发的最先进的开源模型,用于从单个图像中快速前馈3D重建。在NVIDIA A100 GPU上不到0.5秒就能生成高质量的3D模型。 项目链接 https://github.com/VAST-AI-Research/TripoSR TripoSR利用大型重建模型(LRM)的原理,…

恒峰便携式森林灭火泵:森林守护者的强力助手

在茂密的森林中,一场突如其来的火灾可能会带来无法估量的破坏。这不仅会对生态环境造成严重影响,还可能危及人类和动植物的生命安全。为了应对这种突发情况,恒峰研发出了一种便携式森林灭火泵,它成为森林守护者的强力助手。 首先&…

32个关键字详解①(C语言)

目录 关键字分类: 第一个C程序 - 补充内容 变量的定义与声明 - 补充内容 变量的分类 - 补充内容 变量的作用域 - 补充内容 变量的生命周期 - 补充内容 auto 关键字 register 关键字 static 关键字 static 修饰变量: static修饰函数 sizeof 关键字 基本数…

解决windows无法识别外接显示器问题

文章目录 1. 问题2. 解决方法2.1 先尝试重启2.2 检查设备驱动 1. 问题 windows 系统在接入其他显示器时,发现另一个显示器没有生效 2. 解决方法 2.1 先尝试重启 首先你应该至少先尝试重启一次电脑,万能的重启方法! 2.2 检查设备驱动 如…

hadoop报错:HADOOP_HOME and hadoop.home.dir are unset. 解决方法

参考:https://blog.csdn.net/weixin_45735242/article/details/120579387 解决方法 1.下载apache-hadoop-3.1.0-winutils-master 官网下载地址: https://github.com/s911415/apache-hadoop-3.1.0-winutils win配置系统环境: 然后重启idea…

【Python从入门到进阶】50、当当网Scrapy项目实战(三)

接上篇《49、当当网Scrapy项目实战(二)》 上一篇我们讲解了的Spider与item之间的关系,以及如何使用item,以及使用pipelines管道进行数据下载的操作,本篇我们来讲解Scrapy的多页面下载如何实现。 一、多页面下载原理分…

Git LFS【部署 01】Linux环境安装git-lfs及测试

Linux系统安装git-lfs及测试 1.下载2.安装3.测试4.总结 Git LFS(Large File Storage)是一个用于Git版本控制系统的扩展,它专门用来管理大型文件,如图像、音频和视频文件。 1.下载 安装包下载页面:https://github.com/…

数据结构入门篇 之 【单链表】的实现讲解(附单链表的完整实现代码以及用单链表完成通讯录的实现代码)

虽然封面是顶针,但是我们还是要好好学习❀ 一.单链表 1.单链表的概念 2.单链表的结构 3.单链表的实现 1).尾插函数 SLTPushBack 2).打印函数 SLPrint 3). 头插函数 SLTPushFront 4).尾删函数 SLTPopBack 5&am…

[云原生] k8s配置资源管理

一、Secret的资源配置 1.1 Secret配置的相关说明 Secret 是用来保存密码、token、密钥等敏感数据的 k8s 资源,这类数据虽然也可以存放在 Pod 或者镜像中,但是放在 Secret 中是为了更方便的控制如何使用数据,并减少暴露的风险。 Secret 有…

ARM TrustZone技术解析:构建嵌入式系统的安全扩展基石

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-dSk2aQ85ZR0zxnyI {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

STM32利用标准库的方式输出PWM(proteus仿真)

首先打开proteus仿真软件,绘制电路图: 其中示波器的添加很简单的,看图: 再来看看咱们最后程序的效果: 下面就是程序代码了,新建两个文件PWM.c和PWM.h文件,所属关系如图: 整个的编程思…

【Leetcode每日一题】 位运算 - 位1的个数(难度⭐)(32)

1. 题目解析 题目链接:191. 位1的个数 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 核心在于计算题目所给32位二进制数1的个数返回即可。 2.算法原理 位运算特性:通过位运算,特别是按位与(&…

YOLO算法改进Backbone系列之:FocalNet

摘要:本文提出焦调制网络(FocalNets),其中自注意(SA)完全被焦调制模块取代,用于建模视觉中的令牌交互。焦点调制包括三个组成部分:(1)焦点上下文化,使用深度卷积层堆栈实现,从短范围…

【MATLAB第99期】#源码分享 | 基于MATLAB的SHEPard模型多输入单输出回归预测模型

【MATLAB第99期】#源码分享 | 基于MATLAB的SHEPard模型多输入单输出回归预测模型 Shepard模型(简称SP模型)就是一种直观的、可操作的相似预测法,常用于插值。相似预测法基本原理按照相似原因产生相似结果的原则,从历史样本中集中找出与现在的最相似的一…

SpringCloud使用

一 、SpringCloud项目简介 SpringCloud项目可划为三个角色,一个是服务的注册与发现中心(Eureka ),一个是服务的提供方(Provider),最后一个是服务的消费方(Consumer)&…

C语言内存管理-堆内存

堆内存(heap)又被称为动态内存、自由内存,简称堆。堆是唯一可被开发者自定义的区段,开发者可以根据需要申请内存的大小、决定使用的时间长短等。但又由于这是一块系统“飞地”,所有的细节均由开发者自己把握&#xff0…