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

【创建模式-蓝本模式(Prototype Pattern)】

目录

  • Overview
  • 应用场景
  • 代码演示
    • JDK Prototype pattern
  • 更优实践
    • 泛型克隆接口

https://doc.hutool.cn/pages/Cloneable/#%E6%B3%9B%E5%9E%8B%E5%85%8B%E9%9A%86%E7%B1%BB

The prototype pattern is a creational design pattern in software development. It is used when the types of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to avoid subclasses of an object creator in the client application, like the factory method pattern does, and to avoid the inherent cost of creating a new object in the standard way (e.g., using the ‘new’ keyword) when it is prohibitively expensive for a given application.

To implement the pattern, the client declares an abstract base class that specifies a pure virtual clone() method. Any class that needs a “polymorphic constructor” capability derives itself from the abstract base class, and implements the clone() operation.

The client, instead of writing code that invokes the “new” operator on a hard-coded class name, calls the clone() method on the prototype, calls a factory method with a parameter designating the particular concrete derived class desired, or invokes the clone() method through some mechanism provided by another design pattern.

The mitotic division of a cell — resulting in two identical cells — is an example of a prototype that plays an active role in copying itself and thus, demonstrates the Prototype pattern. When a cell splits, two cells of identical genotype result. In other words, the cell clones itself.[1]

Overview

The prototype design pattern is one of the 23 Gang of Four design patterns that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.[2]: 117

The prototype design pattern solves problems like:[3]

  • How can objects be created so that the specific type of object can be determined at runtime?
  • How can dynamically loaded classes be instantiated?
    Creating objects directly within the class that requires (uses) the objects is inflexible because it commits the class to particular objects at compile-time and makes it impossible to specify which objects to create at run-time.

The prototype design pattern describes how to solve such problems:

  • Define a Prototype object that returns a copy of itself.
  • Create new objects by copying a Prototype object.
    This enables configuration of a class with different Prototype objects, which are copied to create new objects, and even more, Prototype objects can be added and removed at run-time.
    See also the UML class and sequence diagram below.

应用场景

  当需要反复构建出同一个类的大量实例,并且这些实例的初始状态都是一样的时候就可以先通过new创建出一个实例,对该实例进行调整(通常就是设置一些参数),这个实例就可以称之为原型,这也是该设计模式叫原型模式的缘由。

  我们可以举一个实际的例子(引用自:《设计模式之禅道》),银行批量向客户发送节日邮件,假设一封邮件包括:①称呼、②节日祝福语;那么操作流程应该是这样的:

  1. 创建一个模板,对该模板设置节日祝福语,因为所有的人节日祝福语是相同的;
  2. 为每一个客户依次克隆一个第一步的模板(如果不新建模板的话,多线程并发时是不安全的,通过new创建效率不如克隆),得到一个实例,将该实例传递给一个发送邮件线程;
  3. 发送线程对传递得到的邮件实例,进行称呼设置,然后进行邮件发送;

代码演示

JDK Prototype pattern

/*** 原型模式 VS 构造函数 性能测试** @author hipilee*/
public class JdkCloneable implements Cloneable {public int properties1 = 0;public JdkCloneable() {}public JdkCloneable(int properties1) {HashMap<Integer, Integer> hashMap = new HashMap(100);for (int i = 0; i < 10; i++) {hashMap.put(properties1, properties1);}}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public static void main(String[] args) throws CloneNotSupportedException {long start, end;start = System.currentTimeMillis();JdkCloneable jdkCloneable = new JdkCloneable(1000);for (int i = 0; i < 10000000; i++) {jdkCloneable.clone();}end = System.currentTimeMillis();System.out.println("原型模式:耗时" + (end - start) / 1000.0 + "毫秒。");start = System.currentTimeMillis();for (int j = 0; j < 10000000; j++) {new JdkCloneable();}end = System.currentTimeMillis();System.out.println("默认构造:耗时" + (end - start) / 1000.0 + "毫秒。");start = System.currentTimeMillis();for (int j = 0; j < 10000000; j++) {new JdkCloneable(j);}end = System.currentTimeMillis();System.out.println("复杂构造:耗时" + (end - start) / 1000.0 + "毫秒。");}
}

输出:

原型模式:耗时0.357毫秒。
简单构造:耗时0.008毫秒。
复杂构造:耗时6.016毫秒。

由此我们可以得出,原型模式相对于new关键字构造对象的优势在于:如果new构造调用的构造函数比较耗时时,原型模式才有明显优势;因为原型模式是从内存中拷贝二进制数据不会调用构造函数。

更优实践

通过使用Hutool工具类,来解决jdk自身的Cloneable接口不方便的地方:

  • java.lang.Cloneable接口是个空接口起标记作用,在对类进行克隆时,如果该类只是实现了java.lang.Cloneable接口并没有重写Object的clone()函数,那么会抛出CloneNotSupportedException异常;
  • Object的clone()函数返回的对象是Object,克隆后需要程序员自己强转下类型;
  • jdk的克隆函数是浅拷贝

泛型克隆接口

实现Hutool的cn.hutool.core.clone.Cloneable接口。此接口定义了一个返回泛型的成员方法,这样,实现此接口后会提示必须实现一个public的clone方法,调用父类clone方法即可:

import cn.hutool.core.clone.CloneRuntimeException;
import cn.hutool.core.clone.Cloneable;/*** 猫猫类,使用实现Cloneable方式* @author Looly**/
class Cat implements Cloneable<Cat>{private String name = "miaomiao";private int age = 2;@Overridepublic Cat clone() {try {return (Cat) super.clone();} catch (CloneNotSupportedException e) {throw new CloneRuntimeException(e);}}
}

相关文章:

【创建模式-蓝本模式(Prototype Pattern)】

目录 Overview应用场景代码演示JDK Prototype pattern 更优实践泛型克隆接口 https://doc.hutool.cn/pages/Cloneable/#%E6%B3%9B%E5%9E%8B%E5%85%8B%E9%9A%86%E7%B1%BB The prototype pattern is a creational design pattern in software development. It is used when the t…...

Spring Boot应用开发深度解析与实战案例

Spring Boot应用开发深度解析与实战案例 在当今快速发展的软件开发领域,Spring Boot凭借其“约定优于配置”的理念,极大地简化了Java应用的开发、配置和部署过程,成为了微服务架构下不可或缺的技术选型。本文将深入探讨Spring Boot的核心特性、最佳实践,并通过一个具体的…...

优化Go语言中的网络连接:设置代理超时参数

网络连接优化的重要性 在分布式系统和微服务架构中&#xff0c;网络请求的效率直接影响到整个系统的响应速度。合理的超时设置可以防止系统在等待网络响应时陷入无限期的阻塞&#xff0c;从而提高系统的吞吐量和用户体验。特别是在使用代理服务器时&#xff0c;由于增加了网络…...

《神经网络与深度学习》(邱锡鹏) 内容概要【不含数学推导】

第1章 绪论 基本概念&#xff1a;介绍了人工智能的发展历程及不同阶段的特点&#xff0c;如符号主义、连接主义、行为主义等。还阐述了深度学习在人工智能领域的重要地位和发展现状&#xff0c;以及其在图像、语音、自然语言处理等多个领域的成功应用。术语解释 人工智能&…...

原创 传奇996_55——后端如何点击npc隐藏主界面

点击图片退出&#xff0c;举例&#xff1a; |linkexit Img|ax0.5|ay0.5|percentx50|percenty50|imgpublic/touming2.png|hideMain1|linkexit <Img|x0|y0|esc1|show4|bg1|move0|imgcustom/new/longhun/bg.png|loadDelay0|reset1|hideMain1>...

RabbitMQ中的Work Queues模式

在现代分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff09;是实现异步通信和解耦系统的关键组件之一。RabbitMQ 是一个广泛使用的开源消息代理软件&#xff0c;支持多种消息传递模式。其中&#xff0c;Work Queues&#xff08;工作队列&#xff09;模式是一…...

GESP202412 四级【Recamán】题解(AC)

》》》点我查看「视频」详解》》》 [GESP202412 四级] Recamn 题目描述 小杨最近发现了有趣的 Recamn 数列&#xff0c;这个数列是这样生成的&#xff1a; 数列的第一项 a 1 a_1 a1​ 是 1 1 1&#xff1b;如果 a k − 1 − k a_{k-1}-k ak−1​−k 是正整数并且没有在数…...

蓝桥杯新年题解 | 第15届蓝桥杯迎新篇

蓝桥杯新年题解 | 第15届蓝桥杯迎新篇 2024年的蓝桥杯即将拉开序幕&#xff01;对于许多编程爱好者来说&#xff0c;这不仅是一次展示自我能力的舞台&#xff0c;更是一次学习和成长的机会。作为一名大一新生的小蓝&#xff0c;对蓝桥杯充满了期待&#xff0c;但面对初次参赛的…...

3D 生成重建035-DiffRF直接生成nerf

3D 生成重建035-DiffRF直接生成nerf 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 本文提出了一种基于渲染引导的三维辐射场扩散新方法DiffRF&#xff0c;用于高质量的三维辐射场合成。现有的方法通常难以生成具有细致纹理和几何细节的三维模型&#xff0c;并且容易出…...

@SpringBootTest 报错: UnsatisfiedDependencyException

Spring Boot Test 报错: UnsatisfiedDependencyException 在使用 SpringBootTest 测试时&#xff0c;出现 UnsatisfiedDependencyException 报错&#xff0c;原因和解决方法如下。 报错原因分析 1. Spring 存在涉及 Bean 没有被添加 Spring Boot 测试中&#xff0c;默认会加…...

mysql、postgresql、oceanbase调优

一、mysql 1、my.cnf [mysqld_safe] log-error=/data/mysql/log/mysql.log pid-file=/data/mysql/run/mysqld.pid[client] socket=/data/mysql/run/mysql.sock default-character-set=utf8[mysqld] basedir=/usr/local/mysql tmpdir=/data/mysql/tmp datadir=/data/mysql/dat…...

MySQL 数据库事务实践

引言 在现代应用程序开发中&#xff0c;确保数据库操作的完整性和一致性至关重要。MySQL 提供了强大的事务管理功能&#xff0c;允许开发者以原子性、一致性、隔离性和持久性&#xff08;ACID&#xff09;的方式处理数据。本文将通过详细的解释和实际示例&#xff0c;带你深入…...

VScode、Windsurf、Cursor 中 R 语言相关快捷键设置

前言 在生物信息学数据分析中&#xff0c;R语言是一个不可或缺的工具。为了提高R语言编程效率&#xff0c;合理设置快捷键显得尤为重要。本文介绍在VSCode Windsurf Cursor 中一些实用的R语言快捷键设置&#xff0c;让非 Rstudio 的 IDE 用起来得心应手&#x1f611; 操作种…...

tcpdump编译

https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz tar -zxvf flex-2.6.4.tar.gz ./configure CFLAGS-D_GNU_SOURCE make sudo make installwget http://ftp.gnu.org/gnu/bison/bison-3.2.1.tar.gz ./configure make sudo make install以上两个库是…...

Linux下禁止root远程登录访问

开始讲故事 Long long ago&#xff0c; Linux远程访问方式有telnet、ssh两种协议&#xff1b;有人可能还会说vnc和rdp协议方式&#xff0c;后面这两种主要是可视化桌面场景下的&#xff0c;并非主流。 时过境迁&#xff0c;telnet因安全性低逐渐被禁用淘汰&#xff0c;最后就…...

算法刷题Day16: BM41 输出二叉树的右视图

题目链接 描述 思路&#xff1a; 递归构造二叉树在Day15有讲到。复习一下&#xff0c;就是使用递归构建左右子树。将中序和前序一分为二。 接下来是找出每一层的最右边的节点&#xff0c;可以利用队列层次遍历。 利用队列长度记录当前层有多少个节点&#xff0c;每次从队列里…...

登录授权的实现:json web token + redis + springboot

文章目录 引言I token实现思路传统JWT TOKEN认证方式改进的JWT TOKEN认证方式redis设计II java代码实现登录接口退出登录接口登录之后接口(token解析和校验)III 常见问题400引言 应用场景: 登录认证 I token实现思路 传统JWT TOKEN认证方式 RESTful API TOKEN认证方式:…...

yolov,coco,voc标记的睡岗检测数据集,可识别在桌子上趴着睡,埋头睡觉,座椅上靠着睡,平躺着睡等多种睡姿的检测,6549张图片

yolov&#xff0c;coco,voc标记的睡岗检测数据集&#xff0c;可识别在桌子上趴着睡&#xff0c;埋头睡觉&#xff0c;座椅上靠着睡&#xff0c;平躺着睡等多种睡姿的检测&#xff0c;6549张图片 数据集分割 6549总图像数 训练组91&#xff05; 5949图片 有效集9&#x…...

数据库表的CRUD

SQL语句&#xff08;Structured Query Language&#xff09;是用于与关系型数据库进行交互的语言。下面是几个常用的SQL语句&#xff1a; 创建表&#xff1a; CREATE TABLE table_name ( column1 datatype, column2 datatype, column3 datatype, ... ); 插入数据&#xff1a; …...

Proxy与Reflect

监听对象操作 在Object中&#xff0c;可以通过defineProperty中的get&#xff0c;set进行监听&#xff0c; Proxy基本使用 有两个参数&#xff0c;第一个是要代理的对象&#xff0c;第二个是捕获器&#xff0c;在不知道捕获器使用哪个之前可以先传个空对象。就会启用默认的捕获…...

技术指标——格雷厄姆指数

文章目录1. 格雷厄姆指数是什么&#xff1f;2. 格雷厄姆指数的作用是什么&#xff1f;3. 举例计算例1&#xff1a;牛市顶部&#xff08;2021年2月&#xff09;例2&#xff1a;熊市底部&#xff08;2024年2月&#xff09;例3&#xff1a;中性水平&#xff08;假设某一般时刻&…...

ollama-QwQ-32B微调实战:定制OpenClaw专属指令集

ollama-QwQ-32B微调实战&#xff1a;定制OpenClaw专属指令集 1. 为什么需要定制OpenClaw指令集 去年冬天&#xff0c;当我第一次用OpenClaw自动整理桌面文件时&#xff0c;发现它总是把"截图"和"截屏"两个文件夹混在一起。这让我意识到&#xff1a;通用大…...

DBA_RECYCLEBIN purge指定日期前的表

SummaryHow to purge DBA_RECYCLBIN for objects older than x days/minutes? or do we have RECYCLEBIN RETENTION feature or truncate recyclebin ?--------------------------------------------------------------------------------------DBA_RECYCLEBIN has a column …...

给汽车ECU做“体检报告”:手把手解读Basetech OCC计数器里的5个关键指标

给汽车ECU做“体检报告”&#xff1a;手把手解读Basetech OCC计数器里的5个关键指标 当一辆车亮起故障灯开进维修车间&#xff0c;维修技师的第一反应往往是连接诊断仪读取数据。但面对屏幕上密密麻麻的OCC计数器数值&#xff0c;很多新手会感到无从下手——这些数字到底在说什…...

老牌CMS的隐痛:从DedeCMS漏洞看开源系统会员模块的安全设计误区

DedeCMS会员模块漏洞剖析&#xff1a;开源系统安全设计的深层反思 当一款拥有百万级安装量的老牌CMS系统曝出前台任意密码修改漏洞时&#xff0c;我们看到的不仅是一个具体的技术缺陷&#xff0c;更是开源项目在安全架构设计上的系统性隐忧。2018年那场影响广泛的DedeCMS漏洞事…...

抖音视频批量下载器:如何快速高效地收集和管理海量抖音内容

抖音视频批量下载器&#xff1a;如何快速高效地收集和管理海量抖音内容 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 抖音作为国内最大的短视频平台&#xff0c;每天产生数以百万计的视频内容&#xff0c;…...

GIS开发必备:5分钟搞定EPSG3857转WGS84坐标转换(附proj4.js完整代码)

GIS开发实战&#xff1a;从原理到代码实现EPSG3857与WGS84的高效坐标转换 刚接触WebGIS开发的工程师们&#xff0c;常常会被各种坐标系搞得晕头转向。为什么高德地图上显示的位置和GPS设备采集的数据对不上&#xff1f;为什么Leaflet、OpenLayers这些库加载的瓦片地图坐标数值大…...

别再手动调API了!用Dify+FastAPI+阿里云OSS,5分钟搭建一个自动化的文生视频服务

从零构建AI视频生成流水线&#xff1a;DifyFastAPIOSS全链路自动化实战 在内容创作领域&#xff0c;视频制作正经历着从手工剪辑到AI生成的范式转移。传统视频制作需要专业软件、复杂操作和大量时间投入&#xff0c;而现代AI技术已经能够通过自然语言描述直接生成高质量视频片段…...

Debian12下Docker国内镜像加速全攻略:以腾讯云为例快速部署WordPress

Debian12下Docker国内镜像加速全攻略&#xff1a;以腾讯云为例快速部署WordPress 在Debian12系统中使用Docker时&#xff0c;国内用户常遇到镜像下载速度慢的问题。本文将详细介绍如何配置国内镜像源加速Docker&#xff0c;并以腾讯云为例&#xff0c;快速部署WordPress环境。…...

R语言新手必看:如何用pkgbuild和Sys.which检查并安装Rtools(附绑定教程)

R语言开发环境配置全指南&#xff1a;从Rtools安装到编译环境搭建 刚接触R语言的开发者&#xff0c;在尝试从源代码编译安装某些扩展包时&#xff0c;常常会遇到"make not found"之类的错误提示。这通常意味着系统缺少必要的编译工具链。本文将详细介绍如何在Windows…...