原型模式 (Prototype Pattern)

定义:

原型模式(Prototype Pattern)是一种创建型设计模式,它用于创建重复的对象,同时保持性能。这种模式的核心思想是通过复制一个已存在的实例来创建新的实例,而不是新建实例并对其进行初始化。原型模式适用于创建复杂对象的情况,特别是当对象创建的成本比较高时,如需要进行繁琐的资源消耗型操作(例如,数据库或文件的读取操作)。

原型模式通常涉及以下几个角色:

  1. 原型(Prototype)
    • 定义用于复制现有对象以生成新对象的接口。
  2. 具体原型(Concrete Prototype)
    • 实现原型接口的类,并提供复制自身的方法。这通常通过实现一个克隆方法(如Java中的 clone() 方法)来完成。
  3. 客户(Client)
    • 创建新的对象时,客户端使用原型实例提供的克隆方法来获取新对象的副本,而不是直接通过new关键字创建。
解决的问题:
  • 高成本的对象创建
    • 当创建一个对象的成本很高时,因为它需要进行复杂的初始化,如从数据库读取数据或进行复杂的计算。原型模式通过复制现有对象来避免这种高成本的创建过程。
  • 避免复杂的构造过程
    • 在某些情况下,对象的创建过程可能涉及多个步骤和要求,使用原型模式可以通过直接复制一个已经创建好的实例来简化创建过程。
  • 动态添加或删除对象
    • 在运行时动态地添加或删除具有特定配置的对象时,原型模式提供了一种方便的方法来复制配置相同的实例。
  • 对象的解耦
    • 有时,系统需要独立于其要创建对象的类。原型模式允许你复制一个对象,而不需要依赖于它们的具体类。
  • 优化性能和内存
    • 使用原型模式可以减少系统的整体资源消耗,因为复制通常比创建全新实例更轻量级。
使用场景:
  • 性能敏感的对象创建
    • 当对象的创建过程涉及昂贵的数据库操作、文件读取、复杂计算或网络调用等,而复制现有对象的成本相对较低时。
  • 避免复杂的初始化步骤
    • 如果一个对象的初始化过程非常复杂,如设置多个字段和依赖,使用原型模式可以通过克隆一个已经初始化的实例来避免这些复杂性。
  • 类不容易获取或无法预知
    • 当需要实例化的类在运行时才确定,或者类的实例化过程隐藏在一些我们无法访问的API后面时。
  • 动态加载或生成对象
    • 在需要根据当前环境或状态动态生成对象的场景中,可以通过复制预先存储的原型来实现。
  • 大量相似对象的场景
    • 当系统需要大量相似对象时,使用原型模式可以避免类初始化时的重复工作。
  • 实现对象的解耦
    • 当需要解耦系统中的对象创建和使用时,原型模式允许用户无需知道对象的具体类型就能创建新实例。
示例代码 1 - 浅拷贝实现:
public class ShallowPrototype implements Cloneable {private String name;public ShallowPrototype(String name) {this.name = name;}// getter和setter@Overridepublic ShallowPrototype clone() throws CloneNotSupportedException {return (ShallowPrototype) super.clone();}
}
示例代码 2 - 深拷贝实现:
public class DeepPrototype implements Cloneable {private String name;private SomeComplexObject complexObject;public DeepPrototype(String name, SomeComplexObject complexObject) {this.name = name;this.complexObject = complexObject;}// getter和setter@Overridepublic DeepPrototype clone() throws CloneNotSupportedException {DeepPrototype cloned = (DeepPrototype) super.clone();cloned.complexObject = new SomeComplexObject(this.complexObject); // 创建新的复杂对象实例return cloned;}
}class SomeComplexObject {private String data;public SomeComplexObject(SomeComplexObject obj) {this.data = obj.data;}// getter和setter
}
主要符合的设计原则:
  1. 开闭原则(Open-Closed Principle):
    • 原型模式支持开闭原则。一旦原型对象被创建并实现了克隆(Clone)方法,你可以通过克隆现有对象来添加新的对象实例,而无需修改现有的代码。
  2. 单一职责原则(Single Responsibility Principle):
    • 原型模式允许将对象创建和业务逻辑分离,使得每个类专注于单一的职责。原型对象专注于如何创建和复制自身的实例。
  3. 里氏替换原则(Liskov Substitution Principle):
    • 在原型模式中,任何继承自原型的新对象都应当能替代原型对象。这符合里氏替换原则,即程序中的对象应该能够被其子类对象所替换,而程序的逻辑不受影响。

原型模式主要通过实现开闭原则和单一职责原则来提高代码的可维护性和可扩展性。通过克隆方法,它允许在运行时动态地创建对象,提供了创建对象的灵活方式,同时避免了复杂的构造过程。

在JDK中的应用:
  • java.lang.Objectclone() 方法
    • 在Java中,所有类都继承自 java.lang.ObjectObject 类提供了一个 clone() 方法,可以用来复制对象。尽管这个方法默认是浅复制,但它提供了实现深复制的基础。
  • Java集合框架
    • 许多Java集合类(如 ArrayList, HashSet, HashMap 等)实现了 Cloneable 接口,提供了 clone() 方法来创建集合的副本。这些集合类的克隆方法通常提供了集合内容的浅复制。
  • 日期和时间对象
    • 诸如 java.util.Date 这样的日期和时间相关类也实现了 Cloneable 接口,允许通过克隆方法来创建日期对象的精确副本。
在Spring中的应用:
  • Bean的原型作用域
    • 在Spring框架中,Bean的作用域默认是单例(singleton),但可以配置为原型(prototype)。当一个Bean被定义为原型作用域时,每次通过容器请求这个Bean时,Spring容器都会创建一个新的Bean实例,而不是返回一个共享的单例实例。这正是原型模式的应用,即每次需要时都创建一个新的对象副本。
  • 解决单例Bean的状态问题
    • 在某些情况下,如果单例Bean包含了可变的数据字段,那么在并发环境下可能会出现数据安全问题。通过将这样的Bean定义为原型作用域,可以为每个请求创建一个新的实例,从而避免了状态共享的问题。

虽然Spring中原型作用域的应用并不广泛,但在需要独立状态或避免共享状态的场景中,原型模式提供了一种有效的解决方案。需要注意的是,与单例Bean相比,原型Bean的生命周期管理、依赖注入和销毁需要更多地由开发者来控制。


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

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

相关文章

jetson xavier NX深度学习环境配置

文章目录 jetson xavier NX深度学习环境配置1. SD卡系统烧录1.1 材料1.2 软件配置1.3 格式化SD卡1.4 系统镜像烧录 2. 环境配置2.1 cuda环境配置2.2 安装依赖库2.3 安装python及依赖环境2.4 安装pytorch环境 jetson xavier NX深度学习环境配置 1. SD卡系统烧录 1.1 材料 SD …

面试题 —— 前端精选(1)

文章目录 前言 阐述 JS 的事件循环 JS 中的计时器能做到精确计时吗?为什么? 如何理解 JS 的异步? 前言 本文章介绍三道围绕 JavaScript 的精选面试题 阐述 JS 的事件循环 事件循环⼜叫做消息循环,是浏览器渲染主线程的⼯作⽅式…

CentOS虚拟机重置账号密码

虚拟机忘记密码了 一般来说,虚拟机的账号密码,工作中都会有文档记录,如果忘记了可以查看文档。但是也有特例,虚拟机的密码没有记录到文档中,尝试了很多次依然登录失败,这时候就只能重置账号密码了。 1.重…

upload-labs关卡13(基于白名单的0x00截断绕过)通关思路

文章目录 前言一、回顾上一关知识点二、靶场第十三关通关思路1、看源代码2、bp进行0x00截断绕过3、蚁剑连接 总结 前言 此文章只用于学习和反思巩固文件上传漏洞知识,禁止用于做非法攻击。注意靶场是可以练习的平台,不能随意去尚未授权的网站做渗透测试…

nginx中proxy_pass的配置

Nginx的官网将proxy_pass分为两种类型: 不带URI方式:只包含IP和端口号的,不带uri(单个/也算uri),比如proxy_pass http://localhost:8080;带URI方式:在端口号之后有其他路径的&#…

思维模型 潘多拉效应

本系列文章 主要是 分享 思维模型 ,涉及各个领域,重在提升认知。越是禁止,越是好奇。 1 潘多拉效应的应用 1.1 潘多拉效应在管理中的应用 通用电气公司曾经推出了一项名为“六西格玛”的管理方法,该方法旨在通过优化业务流程和提…

Linux终端和命令行

文章目录 学习Linux终端和命令行一、常用Linux命令的基本使用(一)放大/缩小终端窗口的字体显示(二)自动补全 二、软件安装三、文件和目录常用命令(一)ls:查看目录内容1.ls命令说明2.Linux下文件…

Peter算法小课堂—前缀和数组的应用

桶 相当于计数排序&#xff0c;看一个视频 桶排序 太戈编程1620题 算法解析 #include <bits/stdc.h> using namespace std; const int R11; int cnt[R];//cnt[t]代表第t天新增几人 int s[R];//s[]数组是cnt[]数组的前缀和数组 int n,t; int main(){cin>>n;for(…

flutter 输入框组件 高度问题

使用的组件名字为 TestField 组件 TestField 配置 占位文字 设置 decoration 属性 InputDecoration 中hintText去掉输入到 输入框的间距 InputDecoration 中contentPadding EdgeInsets.zero去掉边框中的间距 InputDecoration 中 使用 isDense:true设置输入框内文字的颜色 …

Android 11.0 SystemUI 去掉状态栏wifi流量上下行图标功能实现

1.概述 在11.0系统定制rom开发中,在关于systemui的定制功能总,在SystemUI 状态栏上显示时钟,电池电量 wifi图标,在显示wifi图标时,网络实时更新时,但是会时不时显示上下行图标 显得很不美观,客户需求要求不显示上下行图标,所以需要去掉上下行图标功能,接下来实现相关功能…

MATLAB算法实战应用案例精讲-【图像处理】计算机视觉(基础篇)(二)

目录 知识储备 opencv基础知识 01 什么OpenCV 02 如何部署OpenCV? 03 OpenCV模块简介 04 OpenCV基本数据结构

Shell循环:for(一)

语法结构&#xff1a; for 变量名 [ in 取值列表] do 循环体 done 示例1&#xff1a; 1、需求&#xff1a;自动循环创建10个用户 2、演示&#xff1a; [rootlocalhost ~]# vim for.sh #脚本编写 #!/bin/bash for i in {1..10} do useradd "user$…

Linux进程通信之共享内存

文章目录 共享内存原理申请共享内存函数&#xff08;shmget&#xff09;参数key生成key值示例申请共享内存 挂接到进程地址空间函数(shmat)去关联函数(shmdt)控制共享内存(shmctl)IPC_STATIPC_RMID ipcs其余进程获取该共享内存进程间通信 进程间通信&#xff1a;IPC&#xff0c…

在openSUSE-Leap-15.5-DVD-x86_64中使用deepin-wine-6.0.0.19再使用金山打字通2016

在openSUSE-Leap-15.5-DVD-x86_64中使用deepin-wine-6.0.0.19再使用金山打字通2016 在openSUSE Software官网输入关键字deepin-wine搜索得到fedora-deepin-wine6的作者是xuthus5 https://software.opensuse.org/package/fedora-deepin-wine6 在百度贴吧fedora吧的《fedora下的…

C++11『lambda表达式 ‖ 线程库 ‖ 包装器』

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2022 版本 17.6.5 文章目录 &#x1f307;前言&#x1f3d9;️正文1.lambda表达式1.1.仿函数的使用1.2.lambda表达式的语法1.3.lambda表达式的使用…

数据结构-深度优先搜索Java实现

目录 一、引言二、算法步骤三、原理演示递归实现非递归实现&#xff08;使用堆栈&#xff09; 四、代码实战五、结论 一、引言 深度优先搜索&#xff08;DFS&#xff09;是一种在图或树中进行搜索的算法&#xff0c;它沿着树的深度遍历树的节点&#xff0c;尽可能深的搜索树的分…

使用C++从0到1实现人工智能神经网络及实战案例

引言 既然是要用C++来实现,那么我们自然而然的想到设计一个神经网络类来表示神经网络,这里我称之为Net类。由于这个类名太过普遍,很有可能跟其他人写的程序冲突,所以我的所有程序都包含在namespace liu中,由此不难想到我姓刘。在之前的博客反向传播算法资源整理中,我列举…

CTF-PWN-QEMU-前置知识

文章目录 QEMU 内存管理(QEMU 如何管理某个特定 VM 的内存)MemoryRegion gpa->hpaFlatView&#xff1a;表示MR 树对应的地址空间FlatRange&#xff1a;存储不同MR对应的地址信息AddressSpace&#xff1a;不同类型的 MemoryRegion树RAMBlock总体简化图 QEMU 设备模拟 &#x…

【Java进阶开发实战】用Java中的Base64数据加密与解密处理

简介 ​ Base64编码,是我们程序开发中经常使用到的编码方法。它是一种基于用64个可打印字符来表示二进制数据的表示方法。它通常用作存储、传输一些二进制数据编码方法, 也是MIME(多用途互联网邮件扩展,主要用作电子邮件标准)中一种可打印字符表示二进制数据的常见编码方法…

Proteus下仿真AT89C51报“串行口通信失败,请检查电平适配是否正确。”解决办法

在Proteus下进行AT89C51串行口仿真时&#xff0c;如果遇到“串行口通信失败&#xff0c;请检查电平适配是否正确”的错误提示&#xff0c;以下是一些解决办法&#xff1a; 1. 了解AT89C51和外部设备的电平要求&#xff1a; 首先&#xff0c;了解AT89C51和外部设备之间的电平…