设计模式-多例模式

设计模式专栏

    • 模式介绍
    • 多例模式和单例模式的区别
    • 应用场景
    • 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://www.mzph.cn/news/583169.shtml

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

相关文章

西北大学844计算机类考研-25级初试高分总攻略

西北大学844计算机类考研-25级初试高分攻略 个人介绍 ​ 本人是西北大学22级软件工程研究生&#xff0c;考研专业课129分&#xff0c;过去一年里在各大辅导机构任职&#xff0c;辅导考研学生专业课844&#xff0c;辅导总时长达400小时&#xff0c;辅导学生超过20余人&#xf…

Android集成OpenSSL实现加解密-集成

导入so 将编译生成的 OpenSSL 动态库文件&#xff08;.so 文件&#xff09;复制到你的 Android 项目的 libs 目录中 导入头文件 将编译生成的include文件夹导入到项目中 build.gradle添加配置 defaultConfig {……testInstrumentationRunner "androidx.test.runner…

java对象整理

1.对象的创建过程 首先class文件加载到内存中 这个过程如下 “加载”是“类加载”(Class Loading)过程的第一步。这个加载过程主要就是靠类加载器实现的&#xff0c; 包括用户自定义类加载器。 加载到内存后做的事情 申请对象内存 成员变量赋默认值 调用构造方法 成员变量顺序…

V-rep(CoppeliaSim)添加相机,与python联合仿真,并使用python读取V-rep中的RGB图与深度图

目录 前言在V-rep中构建场景建立python与V-rep通信 前言 本文主要介绍了如何使用python与V-rep联合仿真&#xff0c;并用OpenCV可视化V-rep中视觉传感器所能看到的 RGB图和深度图&#xff0c;效果图如下。 在V-rep中构建场景 本文使用的V-rep版本是3.5&#xff1a; 打开V-…

009:vue结合el-table实现表格行拖拽排序(基于sortablejs)

文章目录 1. 实现效果2. 安装 sortablejs 插件3. 完整组件代码4. 注意点 1. 实现效果 2. 安装 sortablejs 插件 sortablejs 更多用法 cnpm i --save sortablejs3. 完整组件代码 <template><div class"home"><div class"body"><el-ta…

MongoDB 面试题

MongoDB 面试题 1. 什么是MongoDB&#xff1f; MongoDB是一种非关系型数据库&#xff0c;被广泛用于大型数据存储和分布式系统的构建。MongoDB支持的数据模型比传统的关系型数据库更加灵活&#xff0c;支持动态查询和索引&#xff0c;也支持BSON格式的数据存储&#xff0c;这…

从外网访问内网服务器:安装到使用一站通

如果你所在的是一个小的实验室&#xff0c;可能并没有大型的服务器集群而是仅是配备了小型服务器&#xff0c;日常工作便是在在局域网内访问服务器进行各项数据处理。因为在外网无法访问内网服务器&#xff0c;极大的限制了我们偶尔在外想监测一下数据的欲望。本文介绍了一种简…

postman win7 低版本 postman7.0.9win64 postman7.0.9win32

百度网盘&#xff1a; postman7.0.9win64&#xff1a; 链接: https://pan.baidu.com/s/18ck9tI0r9Pqoz36MOwwnnQ 提取码: rkf7 postman7.0.9win32&#xff1a; 链接: https://pan.baidu.com/s/1HrpGPrgvVzyAcjdHuwVOpA 提取码: ke5k win7系统安装postman&#xff0c;可能会…

postman使用-04响应

文章目录 响应响应界面说明Pretty&#xff1a;格式化显示&#xff0c;以便查看Raw&#xff1a;不进行任何处理&#xff0c;显示响应数据的原始格式Preview&#xff1a;预览响应体&#xff0c;会自动换行&#xff0c;不会格式化&#xff08;有时候是数据&#xff0c;有时候是页面…

实战 | 使用OpenCV快速去除文档中的表格线条(步骤 + 源码)

导 读 本文主要介绍如何使用OpenCV快速去除文档中的表格线条,并给详细步骤和代码。 背景介绍 测试图如下,目标是去除下面三张图中的表格线条,方便后续图像处理。 实现步骤 下面演示详细步骤,以图1为例: 【1】获取二值图像:加载图像、转为灰度图、OTSU二值化 i…

日本it培训班,日本IT大体分几类?

日本是一个老龄化极其严重的国家&#xff0c;拜泡沫经济破灭后的经济停滞所赐&#xff0c;民众取得了节育方面的丰硕成果&#xff0c;然而当经济终于走出阴霾&#xff0c;呈现复苏迹象时&#xff0c;短缺的劳动力又成了一大问题&#xff0c;拖累整个经济的步伐。为了应对劳工市…

仪表盘、数据分析新增分享功能及应用服务下新增服务实例菜单

近期&#xff0c;博睿数据根据一体化智能可观测平台 Bonree ONE 产品本身&#xff0c;以及用户反馈进行持续的更新和优化。以下为 Bonree ONE 产品功能更新报告第03期内容&#xff0c;更多探索&#xff0c;未完待续。 本次迭代的更新集中在平台的仪表盘、数据分析新增分享功能&…

C++面向对象(OOP)编程-C++11新特性详解

C11作为一个重要的版本&#xff0c;引入了很多新的特性&#xff0c;解决了C语言本身很多遗留的内存泄露问题&#xff0c;并且提供了很多比较灵活的用法。引入的auto&#xff0c;智能指针、线程机制都使得C语言的灵活性、安全性、并发性有了很大的提升。 本文会比较详细的介绍C1…

Kubernetes 学习总结(41)—— 云原生容器网络详解

背景 随着网络技术的发展&#xff0c;网络的虚拟化程度越来越高&#xff0c;特别是云原生网络&#xff0c;叠加了物理网络、虚机网络和容器网络&#xff0c;数据包在网络 OSI 七层网络模型、TCP/IP 五层网络模型的不同网络层进行封包、转发和解包。网络数据包跨主机网络、容器…

IntelliJ IDE 插件开发 | (四)开发一个时间管理大师插件

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门IntelliJ IDE 插件开发 |&#xff08;二&#xff09;UI 界面与数据持久化IntelliJ IDE 插件开发 |&#xff08;三&#xff09;消息通知与事件监听IntelliJ IDE 插件开发 |&#xff08;四&#xff09;开发一…

未来编程语言什么样?编译解释兼方为王

○、编程语言的未来&#xff1f; 随着科技的飞速发展&#xff0c;编程语言在计算机领域中扮演着至关重要的角色。它们是软件开发的核心&#xff0c;为程序员提供了与机器沟通的桥梁。那么&#xff0c;在技术不断进步的未来&#xff0c;编程语言的走向又将如何呢&#xff1f; …

【银行测试】金融银行-理财项目面试/分析总结(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 银行理财相关的项…

CSS 纵向扩展动画

上干货 <template><!-- mouseenter"startAnimation" 表示在鼠标进入元素时触发 startAnimation 方法。mouseleave"stopAnimation" 表示在鼠标离开元素时触发 stopAnimation 方法。 --><!-- 容器元素 --><div class"container&q…

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

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

关于Echarts的重要属性总结

概要 1.设置图例字体颜色&#xff1a; legend: {//添加位置如下textStyle: {color: #fff // 设置图例文字颜色为白色}} 2.设置序列颜色&#xff1a; series: [{ // 添加位置如下itemStyle: { color: #FFA500 // 设置序列Series颜色}] 3.设置坐标轴单位&#xff1a; xAx…