设计模式篇---代理模式

文章目录

    • 概念
    • 结构
    • 实例
      • 静态代理
      • 动态代理
    • 总结

概念

代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
比如我们想从其他国家买东西,但我们无法直接联系外国的商家,可以找代理商,让他们帮我们处理,我们是客户端,只需要面向代理商即可,只需要把钱交给代理商,剩下的那些操作,比如联系商家、和商家签订协议等我们都不需要关心。

结构

在这里插入图片描述
Subject(抽象主题):它是代理类和真实类的共同接口,这样一来在任何使用真实对象的地方都可以使用代理对象,客户端通常需要针对抽象主题角色进行编程。
Proxy(代理类) :它包含了真实对象的引用,所以可以在任何时候操作真实对象。一般在调用真实对象前后还需要执行其他操作。
RealSubject(真实类–被代理类):真实类中实现了主要的业务操作。客户端可以调用代理类,来间接的调用真实类。

实例

静态代理

我们想从海外买台电脑,用代理模式实现这个流程。
在这里插入图片描述

购买东西的接口

public interface IBuySomething {

    void pay();
}

真实类,也就是被代理类

public class Person implements IBuySomething{
    @Override
    public void pay() {
        System.out.println("付款");
    }
}

代理商,也就是代理类,他来帮我们联系商家

public class Agent implements IBuySomething {

    private IBuySomething person;

    public Agent(IBuySomething person) {
        this.person = person;
    }


    @Override
    public void pay() {
        findBusiness();
        person.pay();
    }

    private void findBusiness() {
        System.out.println("我是代理商,付款之前先找到商家");
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        IBuySomething person;
        person = new Agent(new Person());
        person.pay();
    }
}

打印结果:
在这里插入图片描述
也可以让代理商来替我们的朋友来买东西,只需要再声明一个朋友类,让代理商来代理即可。

朋友类

public class Friend implements IBuySomething{
    @Override
    public void pay() {
        System.out.println("我是朋友,我付款");
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        IBuySomething person;
        person = new Agent(new Friend());
        person.pay();
    }
}

打印结果
在这里插入图片描述
反过来,如果想换一家代理商,那就再创建一个新的代理商类即可。

public class Agent2 implements IBuySomething{
    private IBuySomething person;

    public Agent2(IBuySomething person) {
        this.person = person;
    }


    @Override
    public void pay() {
        findBusiness();
        person.pay();
    }

    private void findBusiness() {
        System.out.println("我是另外一个代理商,付款之前先找到商家");
    }
}

动态代理

以上的这种代理方式叫做静态代理。
静态代理的特点是,一个代理类只能代理一个真实类,或者只能代理一个方法。因为它在执行前就编译成了class文件,不会进行改变了,所以被称为静态代理。
但如果我们想动态的代理不同的真实类,或者代理不同的方法,可以使用动态代理来实现。动态代理可以让系统在运行时根据实际需求来动态的创建代理类。
有关动态代理,有两个重要的类。
Proxy类
Proxy类提供了用于创建动态代理对象的方法。它的主要方法newProxyInstance

    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

该方法即用来创建一个动态代理对象;第一个参数是代理类的类加载器(作用是将.class文件加载到jvm中,进而生成一个对象实例);第二个参数是真实类实现的接口列表;第三个是执行代理方法的具体程序—InvocationHandler。
简单总结下,要想生成一个代理对象,首先得创建class对象(第一个参数的作用),其次得知道代理谁(第二个参数的作用),最后代理的方法是什么(第三个参数)。这样看来,第二个和第三个参数都是动态的,可变的,这也就是代理模式的灵活性。

InvocationHandler
上面的第三个参数InvocationHandler 是一个接口,它只有一个invoke方法

public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

该方法用来处理代理类实例的代理方法,并返回相应的结果。即我们代理的方法写在这个方法里。
第一个参数是代理对象;第二个参数是需要代理的方法;第三个参数是需要执行代理方法的参数。

还是拿买东西的例子来说,我们如果买完东西后,发现不合适,需要退款,这时候我们面向的还是代理商,但如果用静态代理的话,那还是需要再写一个代理退款的类,如果业务方法更多的话,那我们需要创建更多的静态代理类,这样处理起来很麻烦。如果用动态代理的话,就没有这么冗余。我们首先实现一个InvocationHandler,它的invoke方法是用来实现代理对象的方法。

public class AgentHandler implements java.lang.reflect.InvocationHandler {


    private Object object;

    public AgentHandler(Object object) {
        this.object = object;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        findBusiness();
        Object result = method.invoke(object, args);
        return result;
    }

    private void findBusiness() {
        System.out.println("我是代理商,我要先找到商家");
    }
}

我们也增加一个退款的方法

public interface IBuySomething {

    void pay();

    void refund();
}

客户端调用

public class Client {
    public static void main(String[] args) {
        IBuySomething person = new Person();

        InvocationHandler handler = new AgentHandler(person);

        Object o = Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), handler);

        IBuySomething proxy = (IBuySomething) o;
        proxy.refund();

    }
}

打印结果:
在这里插入图片描述

总结

静态代理比较好理解,代理类里面实现了代理的方法。
而动态代理的代理对象是通过Proxy创建的,代理的方法是在InvocationHandler里的invoke方法里,和静态代理对比的话,代理类和代理方法是分离开的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

错题总结(四)

1.【一维数组】输入10个整数&#xff0c;求平均值 编写一个程序&#xff0c;从用户输入中读取10个整数并存储在一个数组中。然后&#xff0c;计算并输出这些整数的平均值。 int main() {int arr[10];int sum 0;for (int n 0; n < 10; n){scanf("%d", &arr…

算法Day25 01子串

01子串 Description 给你一个二进制字符串s&#xff0c;该字符串不含前导零。 如果s包含零个或一个由连续的’1’组成的字段&#xff0c;返回true​​​。否则&#xff0c;返回false Input 输入一个只含01的字符串s 1≤s.length≤100 Output 输出true或false Sample 代码 imp…

坚鹏:中国邮政储蓄银行数字化转型战略、方法与案例培训

中国邮政储蓄银行拥有优良的资产质量和显著的成长潜力&#xff0c;是中国领先的大型零售银行。2016年9月在香港联交所挂牌上市&#xff0c;2019年12月在上交所挂牌上市。中国邮政储蓄银行拥有近4万个营业网点&#xff0c;服务个人客户超6.5亿户。2022年&#xff0c;在《银行家》…

LabVIEW开发新型电化学性能测试设备

LabVIEW开发新型电化学性能测试设备 开发了一种基于Arduino和LabVIEW的新型电化学性能测试装置&#xff0c;专门用于实验电池&#xff0c;特别是在锂硫&#xff08;Li-S&#xff09;技术领域的评估。这种装置结合了简单、灵活的硬件和软件工具&#xff0c;使新科学家能够设计针…

智能优化算法应用:基于被囊群算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于被囊群算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于被囊群算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.被囊群算法4.实验参数设定5.算法结果6.参考文…

实用篇 | 一文快速构建人工智能前端展示streamlit应用

----------------------- &#x1f388;API 相关直达 &#x1f388;-------------------------- &#x1f680;Gradio: 实用篇 | 关于Gradio快速构建人工智能模型实现界面&#xff0c;你想知道的都在这里-CSDN博客 &#x1f680;Streamlit :实用篇 | 一文快速构建人工智能前端展…

谷歌云数据中心利用地热能实现能源转型突破

随着全球气候变化问题日益严重&#xff0c;各大公司纷纷寻求更加可持续的能源解决方案。作为科技巨头的谷歌&#xff0c;近日在内华达州的数据中心取得了突破性的进展&#xff0c;开始使用100%地热能供电&#xff0c;为全球数据中心能源转型树立了新的标杆。 作为全球最大的搜…

VOL-vue 框架 文件上传控件关于大文件上传等待的修改

我的项目在测试voltable列表组件中对阿里云OSS做附件上传时&#xff0c;几十M的文件可能就会需要一段时间来上传&#xff0c;才能有OSS的状态和链接返回。 但是控件VolUpload.vue并没有去在这方面做任何交互体验上的控制&#xff0c;而且VolUpload.vue本身写的几个上传函数都是…

逆序对的数量

归并排序模板题 相关文章 //采用归并排序,归并的过程可以算出逆序对的个数//所有的逆序对个数 /*排序后,两个数都在左边的逆序对数排序后,两个数都在右边的逆序对数如果一个数在左边,一个数在右边,在归并的过程中*/ //左边 < 右边,正常归并。如果左边 > 右边 //那么左边…

Kubernetes简介与部署

一、Kubernetes 简介 1、概念&#xff1a; Kubernetes 又称 k8s&#xff0c;是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化应用和服务&#xff0c;通过 Kubernetes 能够进行应用的自动化部署和扩缩容。(k8s不是容器&#xff0c;而是一套容器编排系统) 官网&…

Java学习笔记——instanceof关键字

instanceof关键字&#xff1a; 作用&#xff1a;保证对象向下转型的安全性在对象向下转型前判断某一对象实例是否属于某个类 判断时&#xff0c;如果对象是null&#xff0c;则 instanceof 判断结果为 false

侯捷C++ (二--STL标准库)

CSTL标准库与泛型编程 STL六大部件 容器 Containers分配器 Allocators 一种用来修饰容器或仿函数或迭代器接口的东西算法 Algorithms迭代器 Iterators适配器 Adapters仿函数 Functors 容器 前闭后开 大致分为两种容器&#xff1a;序列容器&#xff0c;关联容器 所谓关联容器…

C# WPF上位机开发(动态库dll的开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多时候&#xff0c;我们并不希望所有的程序都放到一个exe里面。因为这样相当于把所有的风险都放在了一个文件里里面&#xff0c;既不利于程序的升…

13.触发器

目录 1、创建触发器 1、创建只有一个执行语句的触发器 2、创建有多个执行语句的触发器 2、查看触发器 1、通过SHOW TRIGGERS查看触发器: 2.在triggers 表中查看触发器信息 3、使用触发器 4、删除触发器 1、创建触发器 MySQL 的触发器和存储过程一样&#xff0c;都是嵌…

AttributeError: ‘bool‘ object has no attribute ‘sum‘

AttributeError: ‘bool’ object has no attribute ‘sum’ AttributeError: ‘bool’ object has no attribute ‘sum’ 解决方法 将torch.max(&#xff09;改为torch.argmax&#xff08;&#xff09;查看output和targets的数据类型是否都为tensor 以上就是全部内容&#…

CSS 实现丝滑动画

效果展示 CSS 知识点 animation 综合运用 页面整体布局 <div class"box"><div class"circle"></div> </div>编写基础样式 .box {position: relative;width: 400px;height: 400px;border: 80px solid transparent;border-left:…

JDK8新特性:Lambda表达式规则及用法,方法引用

目录 Lambda表达式是JDK8新增的一种语法格式 1.作用 2.用法规则&#xff1a; 3.方法引用 Lambda表达式是JDK8新增的一种语法格式 1.作用 简化匿名内部类的代码写法 Lambad用法前提&#xff1a;只能简化函数式接口&#xff08;一般加有Funcationallnterface&#xff09;&a…

虚拟机VMware安装centos以及配置网络

目录 1、CentOS7的下载2、CentOS7的配置3、CentOS7的安装4、CentOS7的网络配置 4.1、自动获取IP4.2、固定获取IP 5、XShell连接CentO 准备工作&#xff1a;提前下载和安装好VMware。VMware的安装可以参考这一篇文章&#xff1a;VMware15的下载及安装教程。 1、CentOS7的下载 …

排序算法---选择排序

1.实现流程&#xff1a; 1. 把第一个没有排序过的元素设置为最小值&#xff1b; 2. 遍历每个没有排序过的元素&#xff1b; 3. 如果元素 < 现在的最小值&#xff1b; 4. 将此元素设置成为新的最小值&#xff1b; 5. 将最小值和第一个没有排序过的位置交换 选择排序执行流程…

数据的存储(类型的提升)

在操作负中&#xff0c;我们讲解过整形提升运算符&#xff08;详情请看写文章-CSDN创作中心操作符&#xff08;原码反码补码&#xff09;-CSDN博客写文章-CSDN创作中心&#xff09;&#xff0c;知道CPU都是基于整形运算的&#xff0c;而且每个类型都有其最大存储的整数。 目录…
最新文章