设计模式-多例模式

设计模式专栏

    • 模式介绍
    • 多例模式和单例模式的区别
    • 应用场景
    • Spring中多例模式的优缺点
    • 代码示例
      • Java实现多例模式
      • Python实现多例模式
    • 多例模式在spring中的应用


模式介绍

多例模式是一种创建型设计模式,属于对象创建类型。多例模式的特点是允许一个类有多个实例,并且这些实例都是该类本身。多例模式通常用于设计复杂的系统,例如数据库连接、网络通信等。

多例模式的优点包括:

  1. 可以限制实例数量:多例模式可以限制实例数量,确保系统中只有指定数量的实例存在,避免过多的资源消耗。
  2. 可以复用已有实例:多例模式可以复用已有实例,避免重复创建对象,提高系统性能。
  3. 可以灵活控制实例的生命周期:多例模式可以灵活控制实例的生命周期,可以在需要时创建实例,也可以在不需要时销毁实例,避免浪费系统资源。

多例模式的缺点包括:

  1. 难以扩展:多例模式的实例数量是固定的,难以动态地增加或减少实例数量。
  2. 难以测试:由于多例模式的实例数量是固定的,难以对每个实例进行单独的测试。
  3. 破坏封装性:多例模式需要全局访问实例,这破坏了封装性,使得代码难以维护和扩展。
  4. 代码复杂度高:多例模式的实现需要考虑线程安全、序列化等问题,因此代码复杂度较高。

多例模式可以通过实现一个内部类来管理实例的创建和销毁,这个内部类通常被称为“工厂”或“容器”。多例模式有多种实现方式,包括有上限多例模式和无上限多例模式等。在实际应用中,需要根据具体需求选择适合的实现方式。

在这里插入图片描述

多例模式和单例模式的区别

多例模式和单例模式都属于对象创建类型的模式,但它们在实现和应用上有明显的区别。

首先,单例模式要求一个类只有一个实例,并提供一个全局访问点。这意味着无论在程序中的哪个位置访问该类,都将获得同一个实例。单例模式通常用于需要频繁创建和销毁对象的场景,如线程池、缓存等。单例模式的优点包括提供对唯一实例的受控访问、节约系统资源、提高性能等。缺点是扩展困难、职责过重等。

多例模式则允许一个类有多个实例。多例模式的实现通常需要借助静态工厂方法来向外界提供循环使用的实例。多例模式的应用场景包括管理可重复使用的资源,如数据库连接池、线程池等。多例模式的优点是可以复用已有实例、避免重复创建对象、提高系统性能和资源利用率等。缺点是难以扩展、难以测试、破坏封装性、代码复杂度高。

综上所述,多例模式和单例模式在实现和应用上有明显的区别。单例模式强调唯一性,适用于需要频繁创建和销毁对象的场景;而多例模式则允许有多个实例,适用于管理可重复使用的资源。在实际应用中,需要根据具体需求选择适合的模式。

在这里插入图片描述

应用场景

多例模式是一种创建型设计模式,其应用场景主要在于管理可重复使用的资源,如线程池、数据库连接池等。这些场景中,多例模式能够复用已有实例,避免重复创建对象,从而提高系统性能并避免浪费系统资源。

具体来说,多例模式的应用场景包括:

  1. 数据库连接 :在数据库应用中,通常需要为每个客户端请求创建一个数据库连接。然而,创建新的数据库连接是一项开销较大的操作,而且如果每个请求都创建新的连接,会很快耗尽系统的资源。因此,我们通常会使用多例模式来管理数据库连接。创建一个数据库连接池,该连接池可以预先创建一定数量的数据库连接,并保存在连接池中。当有新的请求需要连接数据库时,系统会先从连接池中获取一个空闲的连接,如果连接池中没有空闲的连接,则等待一段时间或者创建新的连接。当请求结束后,该连接会被放回连接池中,以供其他请求使用。通过这种方式,我们可以重复利用已有的连接,避免频繁创建和销毁连接,提高了系统的性能和稳定性。
  2. EJB无状态会话Bean的实例池 :EJB无状态会话Bean是一种特殊的会话Bean,它不保存客户端的状态。由于无状态会话Bean不需要保存客户端的状态,因此可以重复使用同一个实例来处理多个客户端请求。为了实现这个目标,我们可以使用多例模式来管理无状态会话Bean的实例。创建一个实例池,该池中包含了多个无状态会话Bean的实例。当客户端请求到来时,从实例池中获取一个空闲的实例,处理请求后将该实例放回实例池中,以供其他请求使用。通过这种方式,我们可以复用无状态会话Bean的实例,提高系统的性能和并发处理能力。

总的来说,多例模式的应用场景主要涉及可重复使用的资源管理,通过复用已有实例来提高系统性能和资源利用率。在实际应用中,需要根据具体需求选择适合的实现方式。

在这里插入图片描述

Spring中多例模式的优缺点

在Spring框架中,多例模式(prototype scope)是一种常用的依赖注入模式。以下是多例模式的优缺点:

优点:

  1. 性能更好:每次请求都会创建一个新的Bean实例,避免了单例模式中可能存在的线程安全问题,也避免了共享资源带来的开销。
  2. 降低了耦合度:由于每次请求都有独立的实例,因此降低了Bean之间的耦合度。
  3. 支持原型作用域的Bean的生命周期:在Spring中,使用原型作用域的Bean会在每次请求时重新创建,这使得我们可以利用Spring的AOP(面向切面编程)功能来对Bean进行各种增强操作,例如事务管理、日志记录等。

缺点:

  1. 资源消耗较多:由于每次请求都需要创建一个新的Bean实例,因此如果Bean的创建和销毁开销较大,或者应用的请求量非常大,那么可能会导致资源消耗过多。
  2. 不适合需要跨请求保持状态的Bean:由于多例模式为每个请求创建一个新的实例,因此如果Bean需要在跨请求之间保持状态,那么使用多例模式就不合适了。

多例模式适用于那些需要独立实例的Bean,尤其是那些创建和销毁开销较小、状态不需要跨请求保持的Bean。在选择使用单例模式还是多例模式时,需要根据具体的应用场景和需求来决定。

在这里插入图片描述

代码示例

Java实现多例模式

Java实现多例模式可以使用以下步骤:

  1. 创建一个类,该类将包含一个静态的内部类,用于管理实例的创建和销毁。
  2. 在静态内部类中,使用一个静态的Map来保存实例。Map的键是类名,值是该类的实例。
  3. 在静态内部类中,提供一个静态的工厂方法,用于创建实例。该方法首先检查Map中是否已经存在该类的实例,如果存在则直接返回该实例,否则创建一个新的实例并将其保存到Map中。
  4. 在静态内部类中,提供一个静态的销毁方法,用于销毁实例。该方法从Map中移除该类的实例。
  5. 在外部类中,提供一个公共的静态变量,用于访问内部类的实例。

以下是一个示例代码:

public class MultiInstanceExample {private static class InstanceContainer {private static final Map<String, MultiInstanceExample> instances = new HashMap<>();private static final AtomicInteger counter = new AtomicInteger();public static MultiInstanceExample getInstance() {String className = MultiInstanceExample.class.getName();MultiInstanceExample instance = instances.get(className);if (instance == null) {instance = new MultiInstanceExample();instances.put(className, instance);}return instance;}public static void destroyInstance(MultiInstanceExample instance) {String className = instance.getClass().getName();instances.remove(className);}}private MultiInstanceExample() {}public static MultiInstanceExample getInstance() {return InstanceContainer.getInstance();}public static void destroyInstance(MultiInstanceExample instance) {InstanceContainer.destroyInstance(instance);}
}

在上面的代码中,MultiInstanceExample类是一个多例模式的实现。InstanceContainer是一个静态内部类,用于管理实例的创建和销毁。getInstance()方法返回当前类的唯一实例,如果该实例不存在则创建它。destroyInstance()方法从Map中移除该实例。最后,通过调用MultiInstanceExample.getInstance()来获取当前类的唯一实例。

Python实现多例模式

Python实现多例模式可以使用装饰器或者元类的方式。

以下是使用装饰器实现多例模式的示例代码:

def multi_instance(cls):instances = {}def get_instance(*args, **kwargs):if cls not in instances:instances[cls] = cls(*args, **kwargs)return instances[cls]return get_instance@multi_instance
class MyClass:def __init__(self, name):self.name = namedef say_hello(self):print(f"Hello, {self.name}!")

在上面的代码中,multi_instance是一个装饰器函数,它接受一个类作为参数,并返回一个获取类实例的函数。在这个函数中,我们使用一个字典instances来保存类的实例。当获取实例时,我们首先检查该实例是否已经在instances中,如果是则直接返回,否则创建一个新的实例并将其保存到instances中。

接下来,我们使用@multi_instance装饰器来修饰MyClass类。这样,每次调用MyClass()时,都会返回同一个实例。

以下是使用元类实现多例模式的示例代码:

class MultiInstanceMeta(type):_instances = {}def __call__(cls, *args, **kwargs):if cls not in cls._instances:cls._instances[cls] = super().__call__(*args, **kwargs)return cls._instances[cls]class MyClass(metaclass=MultiInstanceMeta):def __init__(self, name):self.name = namedef say_hello(self):print(f"Hello, {self.name}!")

在上面的代码中,我们定义了一个元类MultiInstanceMeta,它继承自type类。在元类的__call__方法中,我们同样使用一个字典_instances来保存类的实例。当调用类时,我们首先检查该实例是否已经在_instances中,如果是则直接返回,否则创建一个新的实例并将其保存到_instances中。最后,我们在MyClass类的定义中指定了元类为MultiInstanceMeta。这样,每次调用MyClass()时,都会返回同一个实例。

在这里插入图片描述

多例模式在spring中的应用

在Spring框架中,多例模式(prototype scope)是一种常用的依赖注入模式。与单例模式(singleton scope)不同,多例模式为每个请求创建一个新的Bean实例。

在Spring中,可以通过在Bean上使用@Scope("prototype")注解或者在XML配置文件中设置prototype作用域来实现多例模式。

多例模式适用于那些需要独立实例的Bean,例如:

  1. 每次请求都需要一个新的实例。
  2. Bean的状态不需要跨请求保持。
  3. Bean的创建和销毁开销较小。

多例模式可以提高应用的性能和资源利用率,因为它可以避免对单例的过度依赖和线程安全问题。但是,如果Bean的创建和销毁开销较大,或者Bean的状态需要在跨请求之间保持,那么使用单例模式可能更为合适。

在这里插入图片描述

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

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

相关文章

多模态大模型-CogVLm 论文阅读笔记

多模态大模型-CogVLm 论文阅读笔记 COGVLM: VISUAL EXPERT FOR LARGE LANGUAGEMODELS 论文地址 :https://arxiv.org/pdf/2311.03079.pdfcode地址 : https://github.com/THUDM/CogVLM时间 : 2023-11机构 : zhipuai,tsinghua关键词: visual language model效果:&#xff08;2023…

HLS 2017.4 导出 RTL 报错:ERROR: [IMPL 213-28] Failed to generate IP.

软件版本&#xff1a;HLS 2017.4 在使用 HLS 导出 RTL 的过程中产生如下错误&#xff1a; 参考 Xilinx 解决方案&#xff1a;https://support.xilinx.com/s/article/76960?languageen_US 问题描述 DESCRIPTION As of January 1st 2022, the export_ip command used by Vivad…

旧衣回收小程序搭建,稳占回收市场

近几年我国大众的消费水平不断提升&#xff0c;闲置物品也相应增加了不少&#xff0c;尤其是闲置衣服&#xff0c;为了减少资源浪费&#xff0c;旧衣服回收回收行业受到了大众的关注。 目前我国旧衣服回收行业的市场规模达到了300多亿元&#xff0c;旧衣回收行业的商业价值非常…

AI绘图软件,科技之旅绘画

科技与艺术的碰撞总能产生令人惊叹的火花&#xff0c;现在小编要给大家介绍一款引领未来艺术潮流的AI绘图软件——首助编辑高手。这是一款将人工智能与创意绘画完美结合的软件&#xff0c;它将为你打开一扇全新的创意之门。 所需工具&#xff1a; 一个【首助编辑高手】软件 …

跨境电商卖家一般用海外云手机做什么?

近些年&#xff0c;海外云手机在跨境电商领域已经逐渐流行开来&#xff0c;但是对于许多人来说海外云手机还是比较陌生&#xff0c;它有什么作用&#xff1f;它可以用于哪些场景&#xff1f;在本文中&#xff0c;我们将详细跨境电商卖家一般是怎样使用海外云手机的。 1. 海外网…

Windows搭建RTMP视频流服务(Nginx服务器版)

文章目录 引言1、安装FFmpeg2、安装Nginx服务器3、实现本地视频推流服务4、使用VLC或PotPlayer可视化播放器播放视频5、RTSP / RTMP系列文章 引言 RTSP和RTMP视频流的区别 RTSP &#xff08;Real-Time Streaming Protocol&#xff09;实时流媒体协议。 RTSP定义流格式&#xff…

企业级依赖管理: 深入解读 Maven BOM

一、背景 当开发者在一个大型项目中使用 Maven 进行依赖管理时&#xff0c;项目往往会包含多个模块或子项目&#xff0c;并且这些模块会共享相同的依赖项。但是&#xff0c;不同模块可能会独立地指定各自的依赖版本&#xff0c;这可能导致以下问题&#xff1a; 依赖版本不一致…

鸿蒙APP的代码规范

鸿蒙APP的代码规范是为了确保代码质量、可读性和可维护性而定义的一系列规则和标准。以下是一些建议的鸿蒙APP代码规范&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 代码风格&#xff1a; 采用…

【完整思路】2023 年中国高校大数据挑战赛 赛题 B DNA 存储中的序列聚类与比对

2023 年中国高校大数据挑战赛 赛题 B DNA 存储中的序列聚类与比对 任务 1.错误率和拷贝数分析&#xff1a;分析“train_reads.txt”和“train_reference.txt”数据集中的错误率&#xff08;插入、删除、替换、链断裂&#xff09;和序列拷贝数。 2.聚类模型开发&#xff1a;开发…

WPF Button使用漂亮 控件模板ControlTemplate 按钮使用控制模板实例及源代码 设计一个具有圆角边框、鼠标悬停时颜色变化的按钮模板

续前两篇模板文章 模板介绍1 模板介绍2 WPF中的Button控件默认样式简洁&#xff0c;但可以通过设置模板来实现更丰富的视觉效果和交互体验。按钮模板主要包括背景、边框、内容&#xff08;通常为文本或图像&#xff09;等元素。通过自定义模板&#xff0c;我们可以改…

GoogleNetv1:Going deeper with convolutions更深的卷积神经网络

文章目录 GoogleNetv1全文翻译论文结构摘要1 引言2 相关工作3 动机和高层考虑稀疏矩阵 4 结构细节引入1x1卷积核可以减少通道数 5 GoogleNet6 训练方法7 ILSVRC 2014 分类挑战赛设置和结果8 ILSVRC 2014检测挑战赛设置和结果9 总结 论文研究背景、成果及意义论文图表 GoogleNet…

锐捷路由小型综合实验

一、实验拓扑 二、实验目的 1、熟练掌握ospf的配置 2、熟练掌握RIP的配置 3、熟练掌握静态路由的配置 4、熟练掌握各种路由协议之间的引入 5、熟练掌握telnet和ssh的配置 三、实验配置 R1 //配置telent username admin password admin123 enable password admin123 enable…

鸿蒙原生应用再添新丁!搜狐集团、航旅纵横入局鸿蒙

鸿蒙原生应用再添新丁&#xff01;搜狐集团、航旅纵横入局鸿蒙 来自 HarmonyOS 微博12月28日消息&#xff0c;搜狐集团宣布与华为达成全面合作&#xff01;搜狐新闻近期将完成#鸿蒙原生应用#核心功能版本&#xff0c;搜狐视频也启动了#鸿蒙原生应用#开发&#xff01;这不仅是一…

处理HTTP错误响应:Go语言中的稳健之道

开场白&#xff1a;在Web开发中&#xff0c;HTTP错误响应是不可避免的一部分。当请求无法成功完成时&#xff0c;服务器会返回一个错误响应。今天&#xff0c;我们将深入探讨如何在Go语言中优雅地处理这些HTTP错误响应。 知识点一&#xff1a;HTTP错误响应的常见类型HTTP错误响…

阿里云数据库PolarDB费用价格_MySQL版_PolarDB_分布式版

阿里云数据库PolarDB租用价格表&#xff0c;云数据库PolarDB MySQL版2核4GB&#xff08;通用&#xff09;、2个节点、60 GB存储空间55元5天&#xff0c;云数据库 PolarDB 分布式版标准版2核16G&#xff08;通用&#xff09;57.6元3天&#xff0c;阿里云百科aliyunbaike.com分享…

SQL Server 存储过程 触发器 事务处理

CSDN 成就一亿技术人&#xff01; 难度指数&#xff1a;* * CSDN 成就一亿技术人&#xff01; 目录 1. 存储过程的作用 创建存储过程 2. 触发器 触发器的种类 insert触发器 update触发器 delete触发器 测试 3. 事务 开始事务 提交事务 回滚事务 举个实例 在 SQ…

gitlab请求合并分支

直接去看原文: 原文链接:Gitlab合并请求相关流程_source branch target branch-CSDN博客 --------------------------------------------------------------------------------------------------------------------------------- 入口&#xff1a; 仓库控制台的这两个地方都…

第4章 信息收集

本章将阐述信息收集的概念及其作用&#xff0c;进而介绍信息收集阶段的各项渗透测试工作。此外&#xff0c;我们还会介绍 Kali Linux 收录的信息收集工具。希望读者在阅读本章之后能够理解在信息收集阶段的渗透测试工作&#xff0c;并且能够在实际的渗透测试中顺利收集各种必要…

javaWebssh民宿管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh民宿管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模 式开发。开发环境为TOMCAT7.0,My…

Spark编程范例:Word Count示例解析

Apache Spark是一个强大的分布式计算框架&#xff0c;用于处理大规模数据。Word Count示例是Spark入门教程中的经典示例&#xff0c;旨在展示如何使用Spark来进行简单的文本处理和数据分析。本文将深入解析Word Count示例&#xff0c;以帮助大家更好地理解Spark的基本概念和编程…