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

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.mfbz.cn/a/437109.html

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

相关文章

万物皆可Find My,伦茨科技ST17H6x芯片赋能产品苹果Find My功能

苹果的Find My功能使得用户可以轻松查找iPhone、Mac、AirPods以及Apple Watch等设备。如今Find My还进入了耳机、充电宝、箱包、电动车、保温杯等多个行业。苹果发布AirTag发布以来,大家都更加注重物品的防丢,苹果的 Find My 就可以查找 iPhone、Mac、Ai…

深入浅出运维可观测工具(四):如何使用eBPF绘制网络拓扑图

哈喽~又到了我们技术分享环节了。eBPF这个系列自分享以来收到了很多朋友的喜欢,真是让博主又惊又喜,感谢大家的支持。话不多说,今天我们将对如何使用eBPF绘制网络拓扑图做一篇分享,文章较长,干货较多,大家可…

11_Http

文章目录 HttpHttp协议网络模型Http协议的工作流程Http请求报文请求行请求方法请求资源协议版本 请求头空行请求体抓包软件:Fiddler Http响应报文响应行状态码 响应头响应体 请求完整的处理流程 Https 整体流程图: 前端:负责获取数据&#xf…

mysql bug( InnoDB: Error number 22),表突然不能读取

mysql bug( InnoDB: Error number 22),表突然不能读取 bug最开始的bug:表突然不能读取关闭mysql容器,再次重启失败 解决方案不重建容器的几种可能措施重建容器重建如果懒得打命令或者忘记命令可能的run bug&#xff1a…

【MySQL知识体系】第2章 数据库与表的创建(一)

第2章 数据库与表的创建 2.1 数据库操作 2.2 表操作 文章目录 第2章 数据库与表的创建2.1 数据库操作2.1.1 创建第一个数据库2.1.2 更新数据库名称(数据库创建后无法修改名称)2.1.3 删除数据库2.1.4 取个合适的数据库名称 第2章 数据库与表的创建 2.1 数…

Vue2 中通过自定义指令将字母转大写

需求是需要将 Code 录入的字母转为大写 /*** 字母转大写*/function inputHandler(e) {e.target.value e.target.value.toUpperCase();// 触发 input 事件以便 v-model 更新数据e.target.dispatchEvent(new Event("input")); }export default {bind: function (el) {…

教育界杂志《教育界》杂志社教育界编辑部2024年第2期目录

教育视界 小学语文课内外阅读的有效融合策略 任小惠; 2-4 项目化学习在初中音乐教学中的应用探索 毛海蓉; 5-7 探索之窗《教育界》投稿:cn7kantougao163.com 儿童无边界阅读支撑系统的建构与实施 袁干斌;蒯红良; 8-10 中学教学 基于核心素养培养的高…

Mybatis-Plus——07,性能分析插件

性能分析插件 一、导入插件二、SpringBoot中配置环境为dev或test环境三、运行测试————————创作不易,笔记不易,如觉不错,请三连,谢谢~~ MybatisPlus也提供了性能分析插件,如果超过这个时间就停止运行&#xff0…

【系统学习】2-Java进阶知识总结-3-集合-1-补充【泛型、树、数据结构】

文章目录 泛型什么是泛型?常见的泛型标识符泛型类泛型方法泛型接口通配符 树树的基本概念什么是二叉树?二叉树--普通二叉树二叉树--二叉查找树定义规则优缺点 二叉树--平衡二叉树定义规则旋转机制 二叉树--红黑树定义规则红黑规则 常见数据结构总体特点结…

AI-数学-高中-31-统计-总体方差与样本方差(新教材内容)

原作者视频(P158):【统计】【一数辞典】5方差知识补充(中档)(新教材内容)_哔哩哔哩_bilibili 方差研究的实际意义:方差是充分反映一组数据内波动大小程度的代表性描述数值。若一组数据内,方差越…

谷歌seo外链怎么发?

谷歌SEO外链建设,说白了,就是让别的网站放一条或几条链接指向你的网站,这事听着简单,但你凭什么在别人的地盘放自己网站的链接,就算真的能放自己网站的链接,你又是否能保证你发的内容跟自己网站相关&#x…

AI论文速读 | 【综述】城市计算中跨域数据融合的深度学习:分类、进展和展望

题目:Deep Learning for Cross-Domain Data Fusion in Urban Computing: Taxonomy, Advances, and Outlook 作者:Xingchen Zou, Yibo Yan, Xixuan Hao, Yuehong Hu, Haomin Wen(温皓珉), Erdong Liu, Junbo Zhang(张钧…

Java适配器设计模式

Java适配器设计模式这一节后面的内容

面向对象中不可变性

软件设计中的不可变性是一个非常重要的概念,它可以在多个方面提高代码的可靠性、可维护性和安全性。 从开发者角度(代码提供者): 在软件开发过程中,当某个对象的属性是不可变的时候,这意味着这些属性的值…

用java实现A*寻路算法

前言: 最近的开发中遇到了寻路这个知识点,然后去了解了一下最常见的A算法,本会会结合我的理解,用最通俗易懂的话语讲解A算法的原理,下面会给出代码示例。 说到寻路算法,就涉及到了图的遍历,然…

开年采购云服务器,怎么买最划算?看这篇!

在2024年开年之际,对于许多企业和个人而言,采购云服务器已成为一项重要的决策。云服务器以其灵活性、可扩展性和高可用性等特点,吸引了越来越多的用户。然而,市场上的云服务器提供商众多,如何选择一家值得入手的服务商…

Domain Driven Design (DDD)

Domain Driven Design (DDD领域驱动设计)主要是业务分类例如(订单、合同、生产、检测、物流、运输等),独立单元相互不干扰,仅暴露接口的模型。核心在Domain,所有业务模块放这边,当然我们做的时候微服务是一…

如何对接1688平台官方开发平台的商品发布/商品过期处理/商品订单接口?

custom-自定义API操作 API测试 注册开通 1688.custom 1688平台官方开放接口 公共参数 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[…

windows部署ruoyi-vue-pro

前提 安装java 安装maven 安装redis mysql 源代码下载 后端 ruoyi-vue-pro 前端 yudao-ui-admin-vue3 后端项目 配置maven 导入数据 CREATE DATABASE ruoyi_vue_pro;修改mysql连接配置 修改redis 打包项目 mvn clean install package -Dmaven.test.skiptrue启动YudaoSe…

TC397 Tasking CMake Gitlab CI CD 环境配置

文章目录 Aurix Development Studio 新建工程与配置Tasking 环境配置CMake 集成Win CMake MinGW 安装Tasking Toolchain 工具链CMakeLists.txtPowershell 脚本 Gitlab CI CDGithub Link 本篇先演示了ADS新建激活编译工程, 讲述了浮点模型, 链接脚本文件, 静态库集成等的设置, 接…