当前位置: 首页 > news >正文

设计模式之创建型设计模式(一):单例模式 原型模式

单例模式 Singleton

1、什么是单例模式

在软件设计中,单例模式是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。

这意味着无论何时需要该类的实例,都可以获得相同的实例,而不会创建新的对象。

单例模式通常用于控制对资源的访问,例如配置文件、数据库连接,或者共享的实例。

2、为什么使用单例模式

  1. 资源共享:单例模式可以确保在整个应用程序中只有一个实例,从而节省系统资源,避免多次创建相同对象。
  2. 全局访问:通过单例模式,可以在任何需要时轻松访问该类的实例,而无需传递它作为参数。
  3. 懒加载:单例模式可以实现懒加载,即只有在需要时才创建实例,而不是在应用程序启动时就创建。

3、如何实现单例模式

示例场景:设计实现一个 Logger 类,用于记录应用程序中的日志信息。

非单例模式的实现
public class Logger {private List<String> logs = new ArrayList<>();public void log(String message) {logs.add(message);}
}// 在应用程序的不同部分创建Logger实例
Logger logger1 = new Logger();
Logger logger2 = new Logger();logger1.log("Message from logger1");
logger2.log("Message from logger2");System.out.println(logger1.getLogs());  // ['Message from logger1']
System.out.println(logger2.getLogs());  // ['Message from logger2']
单例模式的实现
public class Logger {private static Logger instance;  // 单例实例private List<String> logs = new ArrayList<>();private Logger() {}public static Logger getInstance() {if (instance == null) {instance = new Logger();}return instance;}public void log(String message) {logs.add(message);}public List<String> getLogs() {return logs;}
}// 在应用程序的不同部分获取Logger实例
Logger logger1 = Logger.getInstance();
Logger logger2 = Logger.getInstance();logger1.log("Message from logger1");
logger2.log("Message from logger2");System.out.println(logger1.getLogs());  // ['Message from logger1', 'Message from logger2']
System.out.println(logger2.getLogs());  // ['Message from logger1', 'Message from logger2']
代码对比说明
  1. 资源共享:使用单例模式后,Logger 实例在整个应用程序中是唯一的,确保了日志的全局共享,避免了每次创建实例都生成新对象的问题。
  2. 全局访问:单例模式允许在应用程序的任何地方访问相同的 Logger 实例,而不必传递它。这提高了代码的简洁性和可维护性。
  3. 懒加载:单例模式的实现中,通过 getInstance 方法进行了懒加载,只有在实例不存在时才创建。这确保了在应用程序启动时不会预先创建实例,而是在需要时才进行创建,提高了效率。

4、是否存在缺陷和不足

  1. 全局状态:单例模式引入了全局状态,可能会导致代码的耦合性增加。由于单例在整个应用程序中都是可见的,其他部分可能难以预测它的状态,从而使代码难以理解和维护。
  2. 并发控制:在多线程环境中,需要考虑并发控制的问题。当多个线程同时尝试第一次获取单例实例时,可能会导致创建多个实例。为了解决这个问题,需要引入同步机制,但这会带来性能的开销。
  3. 隐藏依赖关系:使用单例模式可能导致隐藏了类之间的依赖关系,因为它可以在任何地方访问单例实例。这使得代码的结构变得不够清晰,降低了模块化的优势。
  4. 单一职责原则破坏:单例模式通常负责两个职责控制实例化过程和提供全局访问点。这可能违反了单一职责原则,使得代码的职责不够清晰。
  5. 测试困难:由于单例模式创建实例的逻辑通常包含在类内部,很难进行单元测试。测试过程可能会依赖于全局状态,导致测试的不确定性。

5、如何缓解缺陷和不足

  1. 使用依赖注入:考虑使用依赖注入来解决单例模式引入的全局状态问题。通过将依赖项传递给需要它们的类,可以更好地控制类之间的关系。
  2. 懒加载与双重检查锁定:在多线程环境中,可以使用懒加载和双重检查锁定等技术来确保实例的唯一性,并提高性能。
  3. 考虑其他创建型模式:根据具体需求,考虑其他创建型设计模式,如工厂方法模式或建造者模式,以避免单例模式的一些限制。
  4. 避免过度使用:单例模式并不适用于所有情况,避免过度使用。在确保有明确需求时使用,而不是为了方便而滥用。

虽然单例模式存在一些缺点,但在许多情况下,它仍然是一种有效的设计选择。在使用单例模式时,需要仔细权衡其优点和缺点,并根据具体情况选择合适的设计方式。

原型模式 Prototype

1、什么是原型模式

原型模式是一种创建型设计模式,核心思想是通过复制现有对象来创建新对象,而不是通过实例化类,这种创建新对象的方式更加高效,尤其当新对象的创建成本较高时,使用原型模式可以提高性能。

2、为什么使用原型模式

  1. 性能提升:当新对象的创建成本较高时,通过复制现有对象可以避免重复执行初始化和配置的开销,提高对象创建的效率。
  2. 灵活性:原型模式可以在运行时动态配置对象,通过克隆可以得到一个与原始对象相似的新对象,而无需修改结构。
  3. 简化对象创建:原型模式隐藏了对象的创建细节,使得对象的创建更加简单和统一。

3、如何实现原型模式

非原型模式的实现
public class Book {private String title;private String author;public Book(String title, String author) {this.title = title;this.author = author;}// Getters and setters...public Book clone() {return new Book(this.title, this.author);}
}
原型模式的实现
public class Book implements Cloneable {private String title;private String author;public Book(String title, String author) {this.title = title;this.author = author;}// Getters and setters...@Overridepublic Book clone() {try {return (Book) super.clone();} catch (CloneNotSupportedException e) {return null;}}
}

4、是否存在缺陷和不足

  1. 深克隆问题:默认的 clone 方法是浅克隆,即只克隆对象本身,而不克隆其引用类型的成员变量。如果对象包含引用类型的成员变量,可能需要进行深克隆,以避免共享引用对象。
  2. 构造函数不执行:在使用原型模式时,对象的构造函数不会执行,这可能导致某些初始化逻辑未被执行。

5、如何缓解缺陷和不足

  1. 深克隆的实现:如果需要深克隆,可以通过重写 clone 方法,手动克隆引用类型的成员变量,确保新对象独立于原始对象。
  2. 初始化方法:在原型对象中提供一个初始化方法,可以在克隆对象后手动调用该方法,以确保必要的初始化逻辑得以执行。

通过以上缓解措施,可以更好地应对深克隆和构造函数不执行等问题,使得原型模式更加灵活和实用,在实际应用中,根据具体需求和场景选择是否使用原型模式。

相关文章:

设计模式之创建型设计模式(一):单例模式 原型模式

单例模式 Singleton 1、什么是单例模式 在软件设计中&#xff0c;单例模式是一种创建型设计模式&#xff0c;其主要目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 这意味着无论何时需要该类的实例&#xff0c;都可以获得相同的实例&#xff0c;而不会创建…...

Amazon CodeWhisperer 在 vscode 的应用

文章作者:旧花阴 CodeWhisperer 是一款可以帮助程序员更快、更安全地编写代码的工具&#xff0c;可以在他们的开发环境中实时提供代码建议和推荐。亚马逊云科技发布的这款代码生成工具 CodeWhisperer 最大的优势就是对于个人用户免费。以在 vscode 为例&#xff0c;演示安装过程…...

【Java】基于fabric8io库操作k8s集群实战(pod、deployment、service、volume)

目录 前言一、基于fabric8io操作pod1.1 yaml创建pod1.2 fabric8io创建pod案例 二、基于fabric8io创建Service&#xff08;含Deployment&#xff09;2.1 yaml创建Service和Deployment2.2 fabric8io创建service案例 三、基于fabric8io操作Volume3.1 yaml配置挂载存储卷3.2 基于fa…...

uniapp微信小程序下载保存图片流到本地,base64

我们在开发时下载图片或文件&#xff0c;地址基本上都是https的格式&#xff0c;下面来说一下后端返回base64的文件流&#xff0c;是如何下载的 必须把返回的流去掉这一部分&#xff1a;data:image/png;base64&#xff0c;否则下载不了 如我自己的流&#xff1a; data:image/…...

华为数通——企业双出口冗余

目标&#xff1a;默认数据全部经过移动上网&#xff0c;联通低带宽。 R1 [ ]ip route-static 0.0.0.0 24 12.1.1.2 目的地址 掩码 下一条 [ ]ip route-static 0.0.0.0 24 13.1.1.3 preference 65 目的地址 掩码 下一条 设置优先级为65 R…...

送奶APP开发:终极指南

您是否有兴趣使用新鲜牛奶和乳制品&#xff0c;但不想每天早上去乳制品店或最近的商店&#xff1f;借助技术&#xff0c;订购日常用品&#xff08;例如杂货和牛奶&#xff09;变得更加简单。 DailyMoo 是最受欢迎的送奶应用&#xff0c;收入达数百万人民币。因此&#xff0c;投…...

Ngnix之反向代理、负载均衡、动静分离

目录 1. Ngnix 1.1 Linux系统Ngnix下载安装 1.2 反向代理 正向代理&#xff08;Forward Proxy&#xff09;&#xff1a; 反向代理&#xff08;Reverse Proxy&#xff09;&#xff1a; 1.3 负载均衡 1.4 动静分离 1. Ngnix Nginx是一个高性能的开源Web服务器&#xff0…...

(C++)将x减到0的最小操作数--滑动窗口

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…...

回答某位同学的问题:残差网络常用来分类,可以用于回归预测吗?

残差网络可以用于回归预测&#xff0c;以下是我的观点&#xff1a; 残差网络最初是用于计算机视觉和语音识别等分类任务,但它也可以用于回归预测。在回归预测任务中,我们预测的目标变量通常是一个连续值,而不是一个离散的类别。使用残差网络进行回归预测的主要思路是: 定义一个…...

C语言初学5:运算符

一、算数运算符 假设变量 A 的值为 10 运算符描述实例A先赋值后运算C A C为10 A为11A--C A-- C为10 A为9A先运算后赋值C A C为11 A为11--AC --A C为9 A为9 二、位运算符 运算符描述实例&对两个操作数的每一位执行逻辑与操作&#xff0c;如果两个相应的位都为 1&…...

亿某通电子文档安全管理系统任意文件上传漏洞 CNVD-2023-59471

1.漏洞概述 亿某通电子文档安全管理系统是一款电子文档安全防护软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产。亿赛通电子文档安全管理系统UploadFileFromClientServiceForClient接口处存在任意文件…...

产品入门第四讲:Axure动态面板

&#x1f4da;&#x1f4da; &#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; ​​​​​ &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Axure》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还…...

【数据结构】哈希表算法总结

知识概览&#xff08;哈希表&#xff09; 哈希表可以将一些值域较大的数映射到较小的空间内&#xff0c;通常用x mod 质数的方式进行映射。为什么用质数呢&#xff1f;这样的质数还要离2的整数幂尽量远。这可以从数学上证明&#xff0c;这样冲突最小。取余还是会出现冲突情况。…...

微信小程序单图上传和多图上传

图片上传主要用到 1、wx.chooseImage(Object object) 从本地相册选择图片或使用相机拍照。 参数 Object object 属性类型默认值必填说明countnumber9否最多可以选择的图片张数sizeTypeArray.<string>[original, compressed]否所选的图片的尺寸sourceTypeArray.<s…...

github入门基础操作

GitHub是一个基于Git版本控制系统的代码托管平台&#xff0c;它提供了一个方便的平台&#xff0c;让开发者可以在上面存储、管理和分享代码。如果你是一个开发者&#xff0c;那么学习如何使用GitHub是非常重要的&#xff0c;因为它可以帮助你更好地管理你的代码和协作开发。 在…...

Android Studio(3.6.2版本)安装 java2smali 插件,java2smali 插件的使用方法简述

一、Android Studio&#xff08;3.6.2版本&#xff09;安装 java2smali 插件 1、左上角File—>Setting&#xff0c;如下图 2、Setting界面中&#xff1a;点击Plugins—>选择右侧上方Marketplace—>搜索栏输入java2smali&#xff0c;如下图 3、点击Install按钮—>点…...

vscode使用remote ssh到server上 - Node进程吃满CPU

起因&#xff1a;Node进程吃满CPU 分析 我发现每次使用vscode的remote插件登陆到server后&#xff0c;就会出现node进程&#xff0c;不太清楚干什么用的&#xff0c;但是绝对和它有关。 查找原因 首先找到了这篇文章&#xff0c;解决了rg进程的问题&#xff1a; https://blo…...

如何在Go中使用日期和时间

引言 软件的设计是为了让工作更容易完成,对许多人来说,这包括与日期和时间进行交互。日期和时间值在现代软件中无处不在。例如,跟踪汽车何时需要服务并让车主知道,跟踪数据库中的变化以创建审计日志,或者只是比较一个时间和另一个时间来确定一个过程花费了多长时间。因此…...

2023_Spark_实验二十九:Flume配置KafkaSink

实验目的&#xff1a;掌握Flume采集数据发送到Kafka的方法 实验方法&#xff1a;通过配置Flume的KafkaSink采集数据到Kafka中 实验步骤&#xff1a; 一、明确日志采集方式 一般Flume采集日志source有两种方式&#xff1a; 1.Exec类型的Source 可以将命令产生的输出作为源&…...

Koa.js 入门手册:洋葱模型插件机制详解以及常用中间件

前言 Nodejs 提供了 http 能力&#xff0c;我们通过如下代码可以快速创建一个http server服务 const http require(http);http.createServer((req, res) > {res.write(hello\n);res.end();}).listen(3000);使用nodejs提供的原生能力启动一个http server并不麻烦&#xff…...

SGMICRO圣邦微 SGM803B-JXN3G/TR SOT-23-3 监控和复位芯片

特性 适用于MAX803/MAX809/MAX810和ADM803/ADM809/ADM810的卓越升级版 高精度固定检测选项:3V、3.3V和5V 低供电电流:300nA(典型值)上电复位脉冲宽度:150毫秒(最小值) 复位输出选项: 开漏nRESET输出(SGM803B)推挽nRESET输出(SGM809B) . . 推挽复位输出(SGM810B)复位有效电压低至…...

ZGC停顿时间为何突然飙升?3个被90%团队忽略的配置雷区曝光

第一章&#xff1a;ZGC停顿时间为何突然飙升&#xff1f;3个被90%团队忽略的配置雷区曝光 ZGC&#xff08;Z Garbage Collector&#xff09;以亚毫秒级停顿著称&#xff0c;但生产环境中频繁出现 10–50ms 甚至更高停顿&#xff0c;往往并非内存压力所致&#xff0c;而是源于几…...

电路板焊接缺陷解析与预防指南

1. 电路板焊接缺陷全解析作为一名硬件工程师&#xff0c;焊接就像吃饭喝水一样是必备技能。但即使是最资深的工程师&#xff0c;也难免会遇到各种焊接问题。今天我就结合自己多年的实战经验&#xff0c;为大家详细剖析16种最常见的焊接缺陷&#xff0c;从外观特征到成因分析&am…...

OpenCV实战:3种图像降噪滤波器的Python代码对比(附效果图)

OpenCV实战&#xff1a;3种图像降噪滤波器的Python代码对比&#xff08;附效果图&#xff09; 在数字图像处理中&#xff0c;噪声是影响图像质量的主要因素之一。无论是来自传感器的不完美&#xff0c;还是传输过程中的干扰&#xff0c;噪声都会降低图像的清晰度和可用性。对于…...

从数据清洗到结果可视化:一份给地理学新手的R语言geodetector实战避坑指南

从数据清洗到结果可视化&#xff1a;一份给地理学新手的R语言geodetector实战避坑指南 第一次用R语言跑地理探测器时&#xff0c;我盯着满屏的报错信息差点崩溃——明明照着教程一步步操作&#xff0c;为什么别人的代码能跑出漂亮的结果&#xff0c;我的却总在数据导入环节就卡…...

避坑指南:nRF52840蓝牙DFU配置中那些官方文档没细说的‘坑’(基于SDK 17.1.0)

nRF52840蓝牙DFU实战避坑手册&#xff1a;从原理到解决方案的深度解析 在嵌入式开发领域&#xff0c;无线固件升级(DFU)功能已成为蓝牙产品的标配需求。nRF52840作为Nordic Semiconductor的旗舰级蓝牙SoC&#xff0c;配合其完善的SDK支持&#xff0c;理论上应该能够轻松实现这一…...

联想新品入局,AI智能终端市场格局生变

联想新品发布&#xff0c;直击Mac mini“养虾”痛点2026年3月31日&#xff0c;联想集团正式发布YOGA AI Mini与Think AI Tiny两款AI原生智能终端。其中&#xff0c;YOGA AI Mini面向个人消费市场&#xff0c;精准对标当下被众多用户用于运行OpenClaw的Mac mini。Mac mini虽因便…...

MySQL解析器的性能优化:从理论到实践

MySQL解析器的性能优化&#xff1a;从理论到实践 引言 作为一名在数据深渊里捞了十几年 Bug 的女码农&#xff0c;我见过太多因为解析器性能问题导致的数据库瓶颈。在 MySQL 数据库中&#xff0c;解析器的性能直接影响 SQL 语句的处理速度和系统的整体性能。今天&#xff0c;我…...

突破方舟生存进化技术壁垒的智能管理工具

突破方舟生存进化技术壁垒的智能管理工具 【免费下载链接】TEKLauncher Launcher for ARK: Survival Evolved 项目地址: https://gitcode.com/gh_mirrors/te/TEKLauncher 你是否曾因MOD安装顺序错误导致游戏频繁崩溃&#xff1f;是否在搭建私人服务器时被端口配置弄得晕…...

探索MariaDB中的JSON处理

在数据库管理中,处理JSON数据逐渐变得重要,尤其是在需要从复杂的JSON结构中提取信息时。今天,我们将深入探讨如何在MariaDB中使用JSON_SEARCH函数来检查JSON对象中的布尔值true。通过实例,我们将展示如何使用此函数来简化查询过程。 JSON数据的结构 假设我们有一个JSON对…...