通俗易懂的java设计模式(6)-代理模式

news2024/11/24 16:47:50

1.什么是代理模式

为某个对象提供一个代理对象,通过这个代理对象,可以控制对原对象的访问。

通俗的解释:我们电脑桌面上的一个个快接方式,当我们点击这个快捷方式的时候,我们就间接地访问到了这个程序。

2.静态代理

何为静态?即在程序运行之前,代理类已经由程序员写好并生成.class文件了

下面是一个最最简单的例子,目的:使用鸡的代理对象,来帮我们创建鸡这个动物

2.1静态代理的简单代码实现

首先,创建一个接口,他代表所有的动物,规定了动物的所有行为

public interface Animal {
    void cry();
}

下面创建一个被代理对象的实体,这里以鸡为例

public class Chick implements Animal{
    private String name;

    public Chick(String name) {
        this.name = name;
        birth(name);
    }

    private void birth(String name) {
        System.out.println("名字是"+name+"的鸡出生了");
    }

    @Override
    public void cry() {
        System.out.println("我是一只叫"+name+"的鸡");
    }
}

下面是鸡这个动物的代理类,同样也要实现Animal接口

public class ProxyChick implements Animal{
    private String name;
    private Chick chick;

    public ProxyChick(String name) {
        this.name = name;
    }

    @Override
    public void cry() {
        if (chick==null){
            chick = new Chick(name);
        }
        chick.cry();
    }
}

测试使用鸡的代理类来获取鸡

public class ProxyTest {
    public static void main(String[] args){
        ProxyChick chick = new ProxyChick("蔡徐坤");
        chick.cry();
        System.out.println("================");
        chick.cry();
    }
}

在这里插入图片描述

2.2java中应用

spring的Aop

还记得面向面向切面编程吗?他又是如何实现对方法进行加强的呢?其实只要在代理对象调用被代理对象方法的前后加上要增强的内容即可。

我们可以在cry方法前后任意的位置去写我们增强的逻辑,下面就用两个print输出来模拟增强方法。

public class ProxyChick implements Animal{
    private String name;
    private Chick chick;

    public ProxyChick(String name) {
        this.name = name;
    }

    @Override
    public void cry() {
        if (chick==null){
            chick = new Chick(name);
        }
        //在方法之前增强
        System.out.println("一个真正的鳗");
        chick.cry();
        //在方法之后增强
        System.out.println("要学会唱跳rap打篮球");
    }
}

2.3静态代理的优缺点

  • 优点:
    • 使用代理模式,给程序带来了高扩展性
  • 缺点:
    • 为了实现代理模式,带来了额外的工作
    • 由于使用被代理对象之前需要经过代理对象,会增加时间开销
    • 使用静态代理,需要程序员编写大量的代理对象加大工作量

3.动态代理

核心:不用事先为想代理的类创建代理对象

代码实现重点:java.lang.reflect包下提供的Proxy类InvocationHandler接口

下面是简单的动态代理实现流程

3.1动态代理的简单代码实现

前几步和静态代理类似,首先,先创建一个接口,定义行为

public interface Animal {
    void cry();
}

创建接口的实现类,也就是被代理的类

public class Chick implements Animal{
    private String name;

    public Chick(String name) {
        this.name = name;
        birth(name);
    }

    private void birth(String name) {
        System.out.println("名字是"+name+"的鸡出生了");
    }

    @Override
    public void cry() {
        System.out.println("我是一只叫"+name+"的鸡");
    }
}

接下来,就是动态代理的具体实现,创建AnimalInvocationHandler类,他实现了InvocationHandler接口

动态代理流程解析:

1.AnimalInvocationHandler持有一个被代理对象

2.通过代理对象执行的方法,都会被替换成AnimalInvocationHandler中的invoke方法

3.代理对象会在invoke方法中,去执行被代理对象的方法,和invoke方法中其他代码语句

上述的三个步骤,其实就是Spring Aop的主要原理

public class AnimalInvocationHandler<T> implements InvocationHandler {
    //持有一个被代理的对象
    private T target;

    public AnimalInvocationHandler(T target) {
        this.target = target;
    }

    /**
     * 其中的三个参数
     * proxy:表示这个动态代理的对象
     * method:正在执行的方法
     * args:调用方法时传入的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("正在代理执行"+proxy.getClass().getName()+"类的"+method.getName()+"方法");
        Object invoke = method.invoke(target, args);
        System.out.println("代理执行结束~");
        return invoke;
    }
}

测试

public class DynamicProxyTest {
    public static void main(String[] args) {
        //创建出被代理的对象
        Animal chick = new Chick("蔡徐坤");
        System.out.println("======================");
        //创建InvocationHandler,他和被代理对象是相关联的
        InvocationHandler chickHandler = new AnimalInvocationHandler<Animal>(chick);
        //得到代理对象,代理对象执行的每一个方法都会被刚刚InvocationHandler中的invoke方法代替
            Animal chickProxy = (Animal) Proxy.newProxyInstance(Animal.class.getClassLoader(),new Class<?>[]{Animal.class},chickHandler);

        chickProxy.cry();
    }
}

上面的代码解析:首先,chick对象是需要被代理的对象,我们把chick传给了chickHandler,并且,创建代理对象chickProxy时,chickHandler也是作为一个参数传入,最后,代理对象chickProxy中的方法在执行的时候,都被替换成了chickHandler中的invoke方法。

在这里插入图片描述

3.2动态代理的特点

  • 与静态代理不同,在上面的代码实现中,我们没有看到具体的代理类,动态代理中的被代理对象和代理对象,是通过InvocationHandler来完成代理的,所以就无须对每一个类都写一个代理类,只需要同一在invoke方法中修改即可。

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

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

相关文章

附录B:Standard Delay Format(SDF)(下)

文章目录B.4 映射实例(Mapping Examples)传播延迟(Propagation Delay)输入建立时间(Input Setup Time)输入保持时间(Input Hold Time)输入建立和保持时间(Input Setup and Hold Time)输入恢复时间(Input Recovery Time)输入撤销时间(Input Removal Time)周期(Period)脉宽(Pulse…

C#自动化物流仓库WMS系统源码

分享一套C#自动化仓库WMS管理系统源码 MF00426 需要源码学习可私信我获取。 WMS作为现代物流系统中的主要组成部分&#xff0c;是一种多层次存放货物的高架仓库系统&#xff0c;由自动控制与管理系统、货架、巷道式堆垛机、出入库输送机等设 备构成&#xff0c;能按指令自动完…

PHP多进程(二)

上篇文章我们说到父进程应该回收子进程结束之后产生的数据,这样才会不浪费系统资源。 一个程序启动之后&#xff0c;变成了一个进程&#xff0c;进程在以下情况会退出 1&#xff09;运行到最后一行语句 2) 运行时遇到return 时 3) 运行时遇到exit()函数的时候 4) 程序异常的时…

【Dash搭建可视化网站】项目13:销售数据可视化大屏制作步骤详解

销售数据可视化大屏制作步骤详解1 项目效果图2 项目架构3 文件介绍和功能完善3.1 assets文件夹介绍3.2 app.py和index.py文件完善3.3 header.py文件完善3.4 api.py文件和api.ipynb文件完善3.4.1 需求数据获取3.4.2 header.py文件中数据变更3.5 middle.py文件完善3.5.1 中间第一…

24.数组名字取地址变成数组指针,数组名和指针变量的区别

数组名字取地址变成数组指针 1.一维数组名字取地址&#xff0c;变成一维数组指针&#xff0c;加1跳一个一维数组。 int a[10]; a1 跳一个整型元素&#xff0c;是a[1]的地址 a和a1相差一个元素&#xff0c;4个字节 &a 就变成了一个一位数组指针&#xff0c;是int(*p)[10]…

结构体重点知识大盘点

0、结构体基础知识 1、结构体是一些值的集合&#xff0c;这些值被称为成员&#xff0c;它们的类型是可以不同的。&#xff08;与数组相似&#xff0c;但数组元素的类型都是相同的&#xff09;。用来描述由基本数据类型组成的复杂类型。 2、结构体也有全局的和局部的。 3、st…

Hello World with VS 17.4.4 DOT NET MAUI Note

Hello World with VS 17.4.4 DOT NET MAUI Note kagula2023-1-12 Prologue If you touched XAML, well here is a concise guide for you running the first MAUI project. Content System Requirement 【1】Microsoft Windows [Version 10.0.19044.2486] Chinese Language …

Ubuntu Centos Linux End Kernel panic-not syncing:Attempted to kill init!

原问题&#xff1a; 当前系统为 Ubuntu 解决问题步骤&#xff1a; 1、重启电脑&#xff0c;在进入选择版本时&#xff0c;选择 系统高级选项&#xff0c; 我选的是【Ubuntu高级选项】 2、进入一个又很多系统版本的界面&#xff0c;每个版本有三个选项&#xff1a;常规启动版…

如何在 ASP.NET Core 2.X 项目中通过EF Core使用MySQL数据库

目录 一、安装MySql.Data.EntityFrameworkCore 二、创建EF Core上下文类以及相关数据模型类 三、配置连接字符串 四、在Starup.cs中注册数据库服务&#xff08;配置Context类的依赖注入&#xff09; 五、通过数据迁移命令生成数据库 目前EF Core已经支持了MySQL数据库了。…

从零开始带你实现一套自己的CI/CD(四)Jenkins Pipeline流水线

目录一、简介二、Groovy2.1 HelloWorld2.2 Pipeline script from SCM三、Jenkinsfile3.1 拉取代码3.2 代码质量检测3.3 构建代码3.4 制作镜像并发布镜像仓库3.5 部署到目标服务器3.6 完整的Jenkinsfile3.7 参数配置3.8 通过参数构建四、添加邮件通知4.1 配置Jenkins邮件配置4.2…

开源飞控初探(一):无人机的历史

这章先纠正大疆带给无人机外行小白的认知。定义无人机无人机的正式英文名字是Unmanned Aerial Vehicle&#xff0c;缩写为UAV。有人无人的区分&#xff0c;是看飞机能否一直需要人为操控。最简单的场景是&#xff0c;当飞机飞出视线之外时&#xff0c;人已经很难实时根据环境来…

微服务自动化管理【docker compose】

1.什么是docker-compose Docker-Compose项目是Docker官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排 通过编写docker-compose文件可对多个服务同时进行启动/停止/更新(可定义依赖&#xff0c;按顺序启动服务) docker-compose将所管理的容器分为3层结构&#…

Yii2下PHP远程调试PHP5.6/7.2与Xdebug2.5/2.7/3.0 在PHPSTORM下的差异化表现

学习起因&#xff1a;新人学YII2不知道远程调试(远程调试和控制台调试是两件事&#xff0c;同一个原理) 因为yii2框架&#xff0c;设计复杂度非常高&#xff0c;加上php代码的弱类型语言结构&#xff0c;在代码非常复杂的情况下&#xff0c;不采用调试的方式来看源码调用栈&am…

MPLS 虚拟专线 实验

目录 1.拓扑图 2.实验思路 3.主要配置 4.测试 5.实验总结 1.拓扑图 2.实验思路 IGP路由 MPLS Domain 配置MPLS VPN PE之间的MP-BGP邻居关系 CE端与PE端的路由交换 双向重发布&#xff0c;实现路由共享 3.主要配置 R6&#xff1a; *公网环境&#xff1a; [r6]ospf 1 r…

记录robosense RS-LIDAR-16使用过程2

一、安装并使用可视化工具RSView&#xff0c;官网提供了不同版本的安装包&#xff0c;根据个人环境下载解压。本人ubuntu18系统&#xff0c;修改权限&#xff1a;chmod ax run_rsview.sh;然后运行&#xff1a;./run_rsview.sh。该软件每次启动时都要运行./run_rsviewer.sh该软件…

Acwing 1214. 波动数列

题目链接&#xff1a;1214. 波动数列 - AcWing题库 标签&#xff1a;动态规划 &#xff08;字好丑...&#xff09; AC代码&#xff1a; #include<iostream> using namespace std;int f[1005][1005];const int MOD 100000007;//返回正余数 int get_mod(int a,int b) {…

不重复的随机数问题

前言 对于随机数的运用&#xff0c;在开发中经常会用到。有时需要生成不重复的定范围定总量的随机数&#xff0c;比如1~20&#xff0c;需要打乱的1~20中的10个数&#xff0c;那到底怎么做呢? 一、不重复的随机数 我们知道&#xff0c;直接用random会有重复的数字&#xff0…

电商物流云仓的原理是什么?

以云的速度和范围获得胜利  这是一个快速转型时期&#xff0c;封锁、就地避难订单和游览限制扰乱了美国经济的各个范畴&#xff0c;对供给链运营产生了严重影响。在如此动乱的时期&#xff0c;企业正越来越多地转向云优先战略&#xff0c;以使其供给链愈加矫捷和灵敏。  战…

【NI Multisim 14.0原理图文件管理——保存/备份文件及新建电路图页文件】

目录 序言 ⛄1.保存文件 ⛄2.备份文件 ⛄3.新建电路图页文件 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地使用虚拟元器件和仪器、仪表进行电路设计和仿真。 首先启动NI Multisim 14.0&#xff0c;打开如图所示的启动界面&#xff…

CTK Plugin Framework插件框架学习--事件监听

文章目录一、前言二、框架事件三、插件事件四、服务事件五、添加事件监听一、前言 CTK一共有三种事件可以监听&#xff1a; 框架事件插件事件服务事件 但是这些事件只有在变化时才能监听到&#xff0c;如果已经变化过后&#xff0c;进入一个稳定的状态&#xff0c;这时才去监…