当前位置: 首页 > 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;在不知道捕获器使用哪个之前可以先传个空对象。就会启用默认的捕获…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...