安卓常见设计模式6------代理模式(Kotlin版)

1. W1 是什么,什么是代理模式?​

  1. 代理模式(Proxy Pattern)是一种结构型设计模式,用于在访问对象之前或之后提供额外的功能或控制。
  2. 代理模式可以用于各种情况,例如延迟加载、权限控制、日志记录等。​

2. W2 为什么,为什么需要使用代理模式,能给我们编码带来什么好处?​

  1. 控制访问:代理模式可以在访问对象之前或之后添加额外的逻辑。这使得我们可以对对象的访问进行控制,例如权限验证、安全检查、延迟加载等。代理充当了客户端和实际对象之间的中介,可以在不修改实际对象的情况下,通过代理来控制对对象的访问。

  2. 隔离复杂性:通过使用代理模式,我们可以将复杂性分散到不同的对象中。代理类负责处理额外的逻辑,而实际对象可以专注于核心业务。这种隔离性使得代码更加模块化,易于理解和维护。

  3. 提高性能:代理模式可以通过延迟加载(Lazy Loading)来提高性能。当实际对象的创建和初始化过程比较耗时时,可以使用代理来推迟实际对象的创建,只在需要时才进行加载。这样可以减少不必要的开销,提高系统的响应速度。

  4. 增强功能:代理模式可以在不修改实际对象的情况下,为其添加额外的功能。例如,可以在实际对象的方法执行前后进行日志记录、缓存数据、统计信息等。这种增强功能的方式使得我们可以灵活地扩展实际对象的行为,而无需对现有的代码进行修改。

  5. 解耦合:代理模式可以将客户端代码与实际对象解耦合。客户端只需要与代理进行交互,而无需直接访问实际对象。这种解耦合使得系统更加灵活,可以在不影响客户端的情况下替换或修改实际对象。

4. W3,如何使用?下面是代码示例:​

// 假设我们正在开发一个图片加载库,我们希望在加载图片时添加日志记录功能。我们可以使用代理模式来实现这个需求。

首先,我们定义一个接口 ImageLoader,其中包含了加载图片的方法:

interface ImageLoader {fun loadImage(url: String)
}

然后,我们创建一个具体的图片加载类 RealImageLoader,它实现了 ImageLoader 接口:

class RealImageLoader : ImageLoader {override fun loadImage(url: String) {println("Loading image from $url")// 实际的图片加载逻辑}
}

接下来,我们创建一个代理类 ImageLoaderProxy,它实现了 ImageLoader 接口,并持有一个实际的图片加载对象:

class ImageLoaderProxy(private val realImageLoader: RealImageLoader) : ImageLoader {override fun loadImage(url: String) {println("Before loading image")realImageLoader.loadImage(url)println("After loading image")}
}

在代理类中,我们可以在调用实际的图片加载方法之前和之后添加额外的逻辑,比如日志记录。

现在,我们可以在应用程序中使用代理类来加载图片:

fun main() {val realImageLoader = RealImageLoader()val imageLoaderProxy = ImageLoaderProxy(realImageLoader)imageLoaderProxy.loadImage("https://example.com/image.jpg")
}

输出结果如下:

Before loading image
Loading image from https://example.com/image.jpg
After loading image

通过使用代理模式,我们在图片加载过程中添加了日志记录的功能,而不需要修改实际的图片加载类。代理类充当了客户端和实际对象之间的中介,为客户端提供了额外的功能。这种方式可以避免对实际对象的直接访问,并可以方便地添加、修改或删除代理类来实现不同的功能需求。

疑问:我们可以直接访问realImageLoader.loadImage,为什么还需要使用imageLoaderProxy.loadImage呢?岂不是多此一举?

确实,对于简单的情况来说,直接访问 realImageLoader.loadImage 可能会更加直接和简单。代理模式的价值在于它提供了一种额外的层次,可以在访问对象之前或之后添加额外的逻辑和控制。

以下是一些使用代理模式的情况,可以帮助解释为什么需要使用代理而不是直接访问实际对象:

  1. 延迟加载:如果图片加载是一个耗时的操作,直接调用 realImageLoader.loadImage 可能会导致界面卡顿。通过使用代理模式,我们可以在需要加载图片时才实例化实际对象,从而实现延迟加载的效果,并提高用户体验。

  2. 缓存数据:代理模式可以在实际对象的方法调用之前检查缓存,如果缓存中存在所需的图片数据,则直接返回缓存数据,而不需要实际进行加载。这种方式可以减少对实际对象的频繁访问,提高性能。

  3. 权限控制:代理模式可以在实际对象的方法调用之前进行权限验证。例如,只有具有特定权限的用户才能访问某些图片。通过代理模式,我们可以在访问实际对象之前进行权限检查,以确保只有授权用户可以加载图片。

  4. 统计信息:代理模式可以在实际对象的方法调用前后记录统计信息,例如加载次数、加载时间等。这种方式可以帮助我们了解实际对象的使用情况,进行性能优化或监控。

总之,代理模式提供了一种中间层可以在访问对象之前或之后添加额外的逻辑和控制。虽然在某些简单情况下直接访问实际对象可能更加直接,但代理模式在处理延迟加载、权限控制、缓存数据、统计信息等方面具有优势。它提供了一种灵活的方式来管理对象访问和功能扩展,并使系统更具可维护性和扩展性。

以延迟加载为例来说明:

要实现延迟加载,可以使用代理模式来推迟对象的创建或初始化,只在需要时才进行加载。下面是一种实现延迟加载的方法:

定义一个接口或抽象类,表示延迟加载的对象。

interface ImageLoader {fun loadImage(url: String)
}

创建实际的对象类,该类负责实际的加载过程。

class RealImageLoader(private val url: String) : ImageLoader {init {// 在实际对象的构造函数中进行初始化,例如从网络或本地加载图片println("Loading image from $url")}override fun loadImage(url: String) {// 实际的加载逻辑}
}

创建代理类,该类持有实际对象,并在需要时进行实例化和加载。

class ImageLoaderProxy(private val url: String) : ImageLoader {private var realImageLoader: RealImageLoader? = nulloverride fun loadImage(url: String) {if (realImageLoader == null) {realImageLoader = RealImageLoader(url)}realImageLoader?.loadImage(url)}
}

在代理类中,我们使用了延迟加载的策略。当调用 loadImage() 方法时,首先检查实际对象是否已经被实例化,如果没有,则实例化并进行加载。如果已经实例化,则直接调用实际对象的 loadImage() 方法。

这样,当我们使用代理类来加载图片时,实际的图片加载对象只在第一次调用时被创建和初始化,后续调用则直接使用已经加载好的对象,从而实现了延迟加载的效果。

fun main() {val imageLoader = ImageLoaderProxy("https://example.com/image.jpg")// 此时实际的图片加载对象还未被创建和初始化// 第一次调用,会创建并初始化实际的图片加载对象imageLoader.loadImage("https://example.com/image.jpg")// 后续调用,直接使用已加载的图片加载对象imageLoader.loadImage("https://example.com/another_image.jpg")
}

输出结果如下:

Loading image from https://example.com/image.jpg
Loading image from https://example.com/another_image.jpg

通过使用代理模式,我们可以实现延迟加载的效果,只在需要时才创建和初始化实际对象,从而提高性能和资源利用。这种方式特别适用于加载耗时的对象,例如大型图片或复杂的资源。

Thank you for your reading, best regards!

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

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

相关文章

高性能网络编程 - The C10M problem

文章目录 Pre概述回顾C10K实现C10M的挑战思路总结 Pre 高性能网络编程 - The C10K problem 以及 网络编程技术角度的解决思路 概述 在接下来的10年里,因为IPv6协议下每个服务器的潜在连接数都是数以百万级的,单机服务器处理数百万的并发连接&#xff0…

基于单片机智能加湿器控制系统仿真设计

**单片机设计介绍, 698【毕业课设】基于单片机智能加湿器控制系统仿真设计 文章目录 一 概要系统组成总结 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 单片机智能加湿器控制系统仿真设计介绍 单片机智能加湿器控制系统是一种利用微…

Jakarta-JVM篇

文章目录 一.前言1. 1 JVM-堆常用调参1.2 JVM-方法区常用参数1.3 JVM-codeCache 二.JVM内存结构三. 对象创建四. JVM垃圾回收算法4.1 可达性分析算法4.1.1 对象引用4.1.2 回收方法区. 4.2 分代回收4.3 标记清除4.4 标记复制4.5 标记整理 五.垃圾回收器5.1 根节点枚举5.2 安全点…

umi4 React项目使用icon集合

umi项目中使用icon集合。 icon集合:https://icones.js.org/ 测试使用这个ion .umirc.ts文件 icons:{autoInstall:{iconify-json/ion: true,//自动安装iconify-json/ion},include: [ion:social-windows-outline],//要使用的必须把icon类名加到include中…

AndroidStudio 运行报错:Invalid keystore format

AndroidStudio 运行报错:Invalid keystore format 把这玩意儿删了重新打开Android Studio运行一下就好了!!!

esxi 6.7下安装黑裙

esxi上创建一个黑裙系统的虚拟机,用来存资料 一、工具 硬件: 工控机:装有esxi6.7系统(192.168.100.2),配置:3865U,16G内存,120Gmsata120sata硬盘,6个网口 主…

利用Ansible实现批量Linux服务器安全配置

1.摘要 在上一篇<<初步利用Ansible实现批量服务器自动化管理>>文章中, 我初步实现了通过编写清单和剧本来实现多台服务器的自动化管理,在本章节中, 我将利用Ansible的剧本来实现更实用、更复杂一点的功能, 主要功能包括三个:1.同时在三台服务器中增加IP访问控制,只…

211. 添加与搜索单词 - 数据结构设计

211. 添加与搜索单词 - 数据结构设计 题目-中等难度示例1. 题目-中等难度 请你设计一个数据结构&#xff0c;支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。 实现词典类 WordDictionary &#xff1a; WordDictionary() 初始化词典对象void addWord(word) 将…

杂货铺 | citespace的使用

安装教程 【CiteSpace保姆级教程1】文献综述怎么写&#xff1f; &#x1f4da;数据下载 1. 新建文件夹 2. 数据下载 知网高级检索 数据选中导出 &#xff1a;一次500 导出后重命名为download_xxx.txt&#xff0c;放到input文件里 3. 数据转换 把output里的数据复制到data里…

jenkins插件迁移

将Jenkins插件迁移至不同的Jenkins实例或更新插件版本是一项常见的任务。以下是迁移Jenkins插件的一般步骤&#xff1a; 备份现有插件&#xff1a; 在开始迁移之前&#xff0c;首先备份你当前的Jenkins实例以及所有相关的插件。这可以通过复制Jenkins的JENKINS_HOME目录来实现…

Qt实现自定义多选下拉列表

目录 前言1、 功能描述2、代码实现总结 前言 本文记录了一种通过继承 QComboBox 实现下拉列表多选功能的方法。效果如下图所示&#xff1a; 1、 功能描述 普通的下拉列表只支持选择一个选项&#xff0c;在软件开发过程中&#xff0c;经常会遇到下拉列表支持选择多个选项的需…

Mybatis-Plus同时使用逻辑删除和唯一索引的问题及解决办法

1 问题背景 在开发中&#xff0c;我们经常会有逻辑删除和唯一索引同时使用的情况。但当使用mybatis plus时&#xff0c;如果同时使用逻辑删除和唯一索引&#xff0c;会报数据重复Duplicate entry的问题。 举例来说&#xff0c;有表user&#xff0c;建立唯一索引&#xff08;u…

centos 7部署Mysql8.0主从

Mysql官网中关于部署主从的网址 环境准备&#xff1a; 搭建虚拟机和安装Mysql之前的文章中已经涉及&#xff0c;在此不再赘述。 主从IPMysql账号密码主192.168.213.4root/Root1234!从192.168.213.5root/Root1234! 1、主数据库设置 配置my.cnf 一般存放于/etc/。 主从配…

uniapp h5实现Excel、Word、PDF文件在线预览,而不是跳转下载,也不需要下载

实现方案 word&#xff0c;微软 Office Web Viewer const url https://view.officeapps.live.com/op/view.aspx?src${encodeURIComponent(https://501351981.github.io/vue-office/examples/dist/static/test-files/test.docx)} window.open(url) //新建窗口打开链接预览 /…

idea使用git删除本地提交(未推送)

1、找到reset head 2、打开弹窗&#xff0c;在HEAD后面输入^ 结果为HEAD^ 注释&#xff1a; Reset Type 有三种&#xff1a; Mixed&#xff08;默认方式&#xff09;&#xff0c;保留本地源码&#xff0c;回退 commit 和 index 信息&#xff0c;最常用的方式Soft 回退到某个版本…

用于图像处理的高斯滤波器 (LoG) 拉普拉斯

一、说明 欢迎来到拉普拉斯和高斯滤波器的拉普拉斯的故事。LoG是先进行高斯处理&#xff0c;继而进行拉普拉斯算子的图像处理算法。用拉普拉斯具有过零功能&#xff0c;实现边缘岭脊提取。 二、LoG算法简述 在这篇博客中&#xff0c;让我们看看拉普拉斯滤波器和高斯滤波器的拉普…

STM32_project:led_beep

代码&#xff1a; 主要部分&#xff1a; #include "stm32f10x.h" // Device header #include "delay.h"// 给蜂鸣器IO口输出低电平&#xff0c;响&#xff0c;高&#xff0c;不向。 //int main (void) //{ // // 开启时钟 // RC…

Git 行结束符:LF will be replaced by CRLF the next time Git touches it问题解决指南

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

怎么学编程效率高,编程练习网站编程软件下载,中文编程开发语言工具下载

怎么学编程效率高&#xff0c;编程练习网站编程软件下载&#xff0c;中文编程开发语言工具下载 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的…

Qt6,使用 UI 界面完成命令执行自动化的设计

一、需要完成的功能 在子对话框&#xff08;CmdChildQt&#xff09;中&#xff0c;点击 “执行” 按钮&#xff0c;将多个命令行指令&#xff0c;依次输入到父对话框&#xff08;CmdQt&#xff09;的编辑框中并且执行&#xff0c;要求如下&#xff1a; 在前一个命令执行完成后&…