Java二十三种设计模式-代理模式模式(8/23)

代理模式:为对象访问提供灵活的控制

引言

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一个代替或占位符,以控制对它的访问。

基础知识,java设计模式总体来说设计模式分为三大类:

(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

第一部分:代理模式概述

1.1 定义与用途

代理模式的基本定义

代理模式是一种结构型设计模式,其核心思想是为一个对象提供一种代理,以控制对这个对象的访问。代理模式可以在不修改目标对象的基础上,通过引入一个代理层来间接操作实际对象,从而实现对目标对象的访问控制、延迟初始化、日志记录、权限校验等功能。

解释为何需要代理模式

访问控制:在某些情况下,我们可能需要对某些对象的访问进行控制,比如限制访问频率、权限验证等。代理模式可以为实际对象提供一个访问控制层,从而实现这些需求。

延迟初始化:有些对象的创建可能是资源密集型的,比如涉及到复杂的计算或者I/O操作。通过代理模式,我们可以延迟对象的初始化,直到真正需要使用时才创建实际对象。

增加额外功能:代理模式可以在不修改实际对象的情况下,为其增加额外的功能,比如日志记录、性能监控、事务处理等。这种方式比修改原有对象的代码更加灵活和安全。

远程代理:在分布式系统中,对象可能位于不同的地址空间。远程代理可以隐藏对象所在的远程地址,并在本地提供一个代理对象,使得客户端感觉就像在访问一个本地对象。

虚拟代理:对于一些需要大量资源来创建的对象,可以使用虚拟代理来提供一个轻量级的替代品。只有当真正需要完整对象时,才会创建实际对象。

保护代理:代理模式还可以用于实现访问保护。通过代理对象,可以控制对实际对象的访问权限,确保只有符合条件的操作才能执行。

智能引用:在某些语言中,代理模式可以用于实现智能引用,比如引用计数、自动内存管理等。

代理模式通过引入一个代理层,提供了一种灵活的方式来增强和控制对象的行为,同时保持了系统的灵活性和可扩展性。在下一部分中,我们将详细介绍代理模式的组成部分和实现方式。

第二部分:代理模式的组成与实现

2.1 角色定义

主题(Subject)

  • 定义:定义了真实对象和代理对象的共同接口,这样代理可以代替真实对象被使用。
  • 角色:充当代理和真实对象的契约。

代理(Proxy)

  • 定义:代理对象内部含有对真实对象的引用,从而可以控制对真实对象的访问。
  • 角色:提供与真实对象相同的接口,并在访问真实对象前或访问后增加额外的处理。

客户端(Client)

  • 角色:通过代理对象来间接访问真实对象,客户端并不直接与真实对象交互。
  • 职责:客户端通过代理对象发送请求,由代理对象来决定如何将请求转发给真实对象。

2.2 Java实现示例

以下是使用Java语言实现代理模式的一个简单示例。我们将创建一个计算资源密集型的对象,并通过代理来控制对该对象的访问。

// 主题接口
interface Subject {
    void request();
}

// 真实对象
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
        // 模拟资源密集型操作
    }
}

// 代理类
class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy() {
        this.realSubject = null;
    }

    public void request() {
        if (realSubject == null) {
            System.out.println("Proxy: Initializing RealSubject...");
            realSubject = new RealSubject();
        }
        realSubject.request();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Subject subject = new Proxy();
        subject.request();
    }
}

在这个示例中,Subject是主题接口,RealSubject是实现了该接口的真实对象。Proxy类实现了与真实对象相同的接口,并在内部持有真实对象的引用。Proxyrequest方法首先检查真实对象是否已经初始化,如果没有,则进行初始化,然后调用真实对象的request方法。

代理模式的变体

  • 远程代理:为远程对象提供代理,隐藏对象的远程地址。
  • 虚拟代理:为开销大的对象提供代理,直到真正需要时才创建实际对象。
  • 保护代理:控制对敏感对象的访问,根据不同的访问权限提供不同的访问策略。
  • 智能引用代理:在访问对象时自动执行额外操作,如引用计数、缓存等。

代理模式通过引入代理层,为对象的访问提供了额外的控制和扩展点,使得可以在不修改对象本身的情况下增加额外的功能。在下一部分中,我们将探讨代理模式的使用场景。

第三部分:代理模式的使用场景

3.1 控制对象访问

在需要控制对复杂对象或远程对象访问时,代理模式非常有用。例如:

  • 访问控制:代理可以检查调用者是否有权限访问真实对象。
  • 远程访问:代理可以作为远程对象的本地代表,隐藏对象的远程地址和通信细节。
  • 延迟加载:代理可以延迟加载重量级的对象,直到它们真正需要时。

3.2 延迟初始化

在需要延迟对象初始化以提高性能或资源利用时,代理模式的优势包括:

  • 性能优化:通过延迟加载,可以减少系统的启动时间,提高响应速度。
  • 资源节约:只有在真正需要时才创建对象,可以节约内存和其他资源。
  • 按需初始化:代理可以根据实际需求来决定是否初始化对象,实现更灵活的控制。

代理模式通过引入代理层,为对象的访问提供了额外的控制和扩展点,使得可以在不修改对象本身的情况下增加额外的功能。在实际开发中,根据具体需求和场景选择是否使用代理模式是非常重要的。

第四部分:代理模式的优点与缺点

4.1 优点

提高安全性

  • 访问控制:代理模式可以对敏感对象的访问进行控制,确保只有符合条件的操作才能执行。

减少资源消耗

  • 延迟初始化:代理模式允许延迟对象的初始化,从而减少不必要的资源消耗。

提升性能

  • 远程代理:通过远程代理,可以在需要时才加载远程对象,从而提高性能。

增加灵活性

  • 动态代理:代理可以在运行时动态地生成,为对象的访问提供灵活的控制。

简化远程通信

  • 远程代理:远程代理可以隐藏对象的远程地址,简化客户端与远程对象的通信。

易于维护

  • 分离关注点:代理模式将访问控制和业务逻辑分离,使得维护和扩展变得更加容易。

4.2 缺点

增加系统复杂性

  • 代理类:为每个需要代理的对象创建代理类可能会增加系统的复杂性。

可能影响性能

  • 额外的间接层:代理模式引入了额外的间接层,可能会对性能产生一定影响。

代理对象的同步问题

  • 多线程环境:在多线程环境中,需要特别注意代理对象的同步问题。

第五部分:代理模式与其他模式的比较

5.1 与装饰者模式的比较

装饰者模式

  • 目的:动态地给对象添加额外的职责。
  • 实现:通过组合来包装对象,增加新的行为。

代理模式

  • 目的:控制对对象的访问。
  • 实现:通过代理对象来间接访问真实对象。

对比

  • 职责:装饰者模式主要用于扩展功能,而代理模式主要用于控制访问。
  • 使用场景:装饰者模式适用于需要动态添加职责的场景,代理模式适用于需要控制对象访问的场景。

5.2 与适配器模式的对比

适配器模式

  • 目的:使不兼容的接口能够一起工作。
  • 实现:通过继承或组合来转换一个类的接口。

代理模式

  • 目的:控制对对象的访问。

对比

  • 接口转换:适配器模式主要用于接口转换,而代理模式主要用于控制对象的访问。
  • 使用场景:适配器模式适用于解决接口不兼容的问题,代理模式适用于需要控制对象访问的场景。

代理模式通过引入代理层,为对象的访问提供了额外的控制和扩展点,使得可以在不修改对象本身的情况下增加额外的功能。在实际应用中,根据具体需求和场景选择合适的设计模式是非常重要的。在下一部分中,我们将提供代理模式的最佳实践和建议。

第六部分:代理模式的最佳实践和建议

6.1 最佳实践

保持代理的透明性

  • 透明代理:代理对象应该尽可能对客户端透明,即客户端与代理对象交互的方式与真实对象相同。

代理的职责单一

  • 单一职责原则:每个代理应该只有一个职责,避免将多个职责混合在一个代理中。

延迟初始化

  • 按需创建:代理应该在第一次请求时才初始化真实对象,以节省资源并提高效率。

考虑线程安全

  • 多线程环境:在多线程环境中使用代理模式时,确保代理对象是线程安全的。

使用代理工厂

  • 工厂模式:通过工厂模式来创建和管理代理对象,可以更好地控制对象的创建和生命周期。

代理的可替换性

  • 可替换性:设计代理时,应确保代理对象可以被其他代理或真实对象替换,以提高系统的灵活性。

6.2 避免滥用

避免过度封装

  • 封装适度:避免过度封装,过度封装可能会隐藏过多的实现细节,使得系统难以理解和维护。

避免代理的复杂性

  • 简单代理:保持代理逻辑的简单性,避免在代理中引入复杂的逻辑。

避免滥用延迟初始化

  • 合理使用延迟初始化:虽然延迟初始化可以节省资源,但过度使用可能会导致系统在关键时刻响应缓慢。

避免代理的滥用

  • 必要性:只在真正需要控制访问或延迟初始化时使用代理模式,避免在不需要时引入不必要的复杂性。

6.3 替代方案

使用依赖注入

  • 依赖注入:通过依赖注入来管理对象的生命周期和依赖关系,而不是使用代理模式。

使用观察者模式

  • 观察者模式:在需要监控对象状态变化时,可以使用观察者模式来代替代理模式。

使用组合模式

  • 组合模式:在需要表示对象的部分-整体层次结构时,可以使用组合模式来代替代理模式。

使用策略模式

  • 策略模式:在需要根据不同的策略动态改变对象行为时,可以使用策略模式来代替代理模式。

使用外观模式

  • 外观模式:在需要简化客户端对复杂系统的访问时,可以使用外观模式来代替代理模式。

代理模式是一种强大的设计模式,可以提供访问控制、延迟初始化等功能。然而,合理使用代理模式并避免滥用是至关重要的。了解其替代方案可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用代理模式,以达到最佳的设计效果。

结语

代理模式提供了一种灵活的方式来控制对对象的访问,同时允许在不修改对象自身的情况下添加额外的职责。通过本文的深入分析,希望读者能够对代理模式有更全面的理解,并在实际开发中做出合理的设计选择。

 相关Java设计模式文章推荐:

Java二十三种设计模式-单例模式(1/23)

Java二十三种设计模式-工厂方法模式(2/23)

Java二十三种设计模式-抽象工厂模式(3/23)

Java二十三种设计模式-建造者模式(4/23)

Java二十三种设计模式-原型模式(5/23)

Java二十三种设计模式-适配器模式(6/23)

Java二十三种设计模式-装饰器模式(7/23) 

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

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

相关文章

【网络】socket和udp协议

socket 一、六个背景知识1、Q1:在进行网络通信时,是不是两台机器在进行通信?2、端口号3、端口号vs进程PID4、目的端口怎么跟客户端绑定的呢?也就是怎么通过目的端口去找到对应的进程的呢?5、我们的客户端,怎…

uniapp小程序上传pdf文件

<template><view class"mainInnBox"><view class"formBox"><!-- 注意&#xff0c;如果需要兼容微信小程序&#xff0c;最好通过setRules方法设置rules规则 --><u-form :model"form" ref"uForm" :rules&quo…

Window版本nginx修改文件访问句柄数被限制,解决大并发量访问时无法响应问题

目录 一、问题背景 二、问题分析 三、解决办法 一、问题背景 Windows版本因为文件访问句柄数被限制为1024了&#xff0c;当大并发量访问时就会无法响应。会有如下错误提示&#xff1a;maximum number of descriptors supported by select() is 1024 while connecting to ups…

C# 基础语法(一篇包学会的)

C#&#xff08;读作"C Sharp"&#xff09;是一种现代的、通用的面向对象编程语言&#xff0c;由微软公司开发。它结合了C和C的强大特性&#xff0c;并去掉了一些复杂性&#xff0c;使得开发者可以更加高效地编写代码。 一、入坑C# (一) 安装和设置 首先&#xff0c…

【LeetCode】从中序与后序遍历序列构造二叉树

目录 一、题目二、解法完整代码 一、题目 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7], …

鸿蒙OpenHarmony Native API【Rawfile】

Rawfile Overview Description: 提供操作rawfile目录和rawfile文件的功能 提供操作rawfile目录和rawfile文件功能 功能包括遍历、打开、搜索、读取和关闭rawfile Since: 8 Version: 1.0 Summary Files File NameDescription[raw_dir.h]提供rawfile目录相关功能[raw…

Debian Linux下rclone挂载谷歌云盘碰到的坑

可能是明月好久没有使用境外服务器挂载境外的云盘缘故吧,今天一个代维客户需要他的Linux服务器挂载谷歌云盘好进行云备份,本来是个很简单的事儿,没想到在rclone连接谷歌云盘的时候卡壳了,可是把明月给难为坏了,搜索到的简体中文教程倒是很多,但没有一个提到这个“坑”,最…

Docker启动PostgreSql并设置时间与主机同步

在 Docker 中启动 PostgreSql 时&#xff0c;需要配置容器的时间与主机同步。可以通过在 Dockerfile 或者 Docker Compose 文件中设置容器的时区&#xff0c;或者使用宿主机的时间来同步容器的时间。这样可以确保容器中的 PostgreSql 与主机的时间保持一致&#xff0c;避免在使…

C语言数组的相关案例

引导案例&#xff1a; 数组的遍历&#xff1a;这里需要注意的是我们在遍历数组时是使用for循环&#xff0c;这里则需要计算数组的长度 计算公式&#xff1a;sizeof(数组名) / sizeof(数组的数据类型) #include<stdio.h> int main() {int arr[] { 1,2,3,4,5,6,7,8 ,9,…

大厂面试-基本功

大厂面试第4季 服务可用性多少个9是什么意思遍历集合add或remove操作bughashcode冲突案例BigdecimalList去重复IDEA Debugger测试框架ThreaLocal父子线程数据同步 InheritableThreadLocal完美解决线程数据同步方案 TransmittableThreadLocal 服务可用性多少个9是什么意思 遍历集…

增值税发票核验API在Java、Python、PHP中的使用教程

在企业经营中&#xff0c;发票扮演着记录交易、报销和纳税的重要角色。然而&#xff0c;由于发票的众多类型和复杂的制作方式&#xff0c;一些企业可能面临着假发票、冒充发票等风险。为了提高财务管理的效率和准确性&#xff0c;以及防范不法行为&#xff0c;增值税发票核验成…

定制QCustomPlot 带有ListView的QCustomPlot 全网唯一份

定制QCustomPlot 带有ListView的QCustomPlot 文章目录 定制QCustomPlot 带有ListView的QCustomPlot摘要需求描述实现关键字: Qt、 QCustomPlot、 魔改、 定制、 控件 摘要 先上效果,是你想要的,再看下面的分解,顺便点赞搜藏一下;不是直接右上角。 QCustomPlot是一款…

Jenkins-zookeeper-docker-xxljob-rancher

文章目录 Jenkins实战1 新建任务需要的配置pipeline Zookeeper基础 Docker基础实操windows11 docker mysql DockerhouseDockerhubxxl-Job基础实战 Rancher基础思考 实战1 Rancher的某个namespace的scale为0 Jenkins 实战 1 新建任务需要的配置pipeline 该代码是Jenkinsfile&…

【接口自动化_08课_Pytest+Yaml+Allure框架】

上节课一些内容 的补充 1、openxl这个方法&#xff0c;第一个元素是从1开始的&#xff0c;不是从0开始 回写的列在程序里写的是11&#xff0c;是因为是固定值 一、1. Yaml入门及应用 1、什么是yaml YAML&#xff08;/ˈjməl/&#xff0c;尾音类似camel骆驼&#xff09;是一…

探索Python日志管理的优雅之道:Loguru库入门指南

探索Python日志管理的优雅之道&#xff1a;Loguru库入门指南 背景&#xff1a;为何选择Loguru&#xff1f; 在Python开发过程中&#xff0c;日志记录是不可或缺的一部分&#xff0c;它帮助我们追踪程序的运行状态&#xff0c;调试程序错误&#xff0c;并记录关键信息。然而&am…

【Linux】-----权限详解

目录 一、Linux下的权限概念 Ⅰ、是什么&#xff1f; Ⅱ、Linux下的两种角色 角色 如何添加普通用户 身份的转化方式 身份的提权 添加普通用户至白名单 二、Linux下的权限管理 Ⅰ、文件访问者的分类(Linux下的“人”) Ⅱ、文件类型和访问权限(事物属性) 1.文件类型 …

使用AOP优化Spring Boot Controller参数:自动填充常用字段的技巧

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 使用AOP优化Spring Boot Controller参数&#xff1a;自动填充常用字段的技巧 前言为什么使用AOP为…

2-41 基于matlab的小车倒立摆系统的控制及GUI动画演示

基于matlab的小车倒立摆系统的控制及GUI动画演示。输入小车及倒立摆的初始参数&#xff0c;位置参数&#xff0c;对仿真时间和步长进行设置&#xff0c;通过LQR计算K值&#xff0c;进行角度、角速度、位置、速度仿真及曲线输出&#xff0c;程序已调通&#xff0c;可直接运行。 …

昇思MindSpore学习总结十七 —— 基于MindSpore通过GPT实现情感分类

1、要求 2、导入了一些必要的库和模块 以便在使用MindSpore和MindNLP进行深度学习任务时能使用各种功能&#xff0c;比如数据集处理、模型训练、评估和回调功能。 import os # 导入操作系统相关功能的模块&#xff0c;如文件和目录操作import mindspore # 导入MindSpore库&a…