【设计模式-原型】

**原型模式(Prototype Pattern)**是一种创建型设计模式,旨在通过复制现有对象的方式来创建新对象,而不是通过实例化类来创建对象。该模式允许对象通过克隆(复制)来创建新的实例,因此避免了重新创建对象带来的开销,尤其在对象创建复杂、耗时的情况下。

1. 定义

原型模式使用一个现有的对象作为原型,创建新对象时,通过克隆该对象来生成新对象。这个模式提供了一个接口来复制已有对象,并允许客户端通过该接口请求复制对象。

2. 原型模式的结构

原型模式主要包含以下几个部分:

  • Prototype(原型接口):定义了一个 clone() 方法,用于克隆自身。具体实现可以是浅拷贝或深拷贝。
  • ConcretePrototype(具体原型类):实现了 Prototype 接口,并实现 clone() 方法。通常使用 Java 的 Cloneable 接口来实现克隆。
  • Client(客户端):通过调用原型的 clone() 方法来获取对象,而不是直接通过构造函数创建对象。

3. 原型模式的工作原理

原型模式的关键在于提供一个能够复制自身的原型接口,并在具体类中实现该接口的 clone() 方法。通过克隆现有对象来创建新对象,这样既节省了资源,又能提高系统性能。

3.1 浅拷贝 vs 深拷贝
  • 浅拷贝:复制对象时,拷贝所有字段,但如果字段是对象类型,则只复制对象的引用。换句话说,浅拷贝只是复制了对象的内存地址,因此新旧对象共享相同的引用类型字段。
  • 深拷贝:不仅复制字段,还会递归地复制引用类型的对象,确保新对象是独立的,彼此不共享任何状态。

4. 原型模式的 UML 类图

在这里插入图片描述

5. Java 中的原型模式示例

Java 提供了 Cloneable 接口和 Object 类中的 clone() 方法,支持原型模式的实现。

5.1 示例代码
class Prototype implements Cloneable {private String name;private int age;public Prototype(String name, int age) {this.name = name;this.age = age;}// 实现 clone 方法@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();  // 浅拷贝}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Prototype{name='" + name + "', age=" + age + "}";}
}public class PrototypePatternDemo {public static void main(String[] args) {try {// 创建原型对象Prototype original = new Prototype("Alice", 25);System.out.println("Original Object: " + original);// 克隆原型对象Prototype clone = (Prototype) original.clone();System.out.println("Cloned Object: " + clone);// 修改原始对象,会影响克隆对象System.out.println("Objects are different: " + (original != clone));} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}

输出:

Original Object: Prototype{name='Alice', age=25}
Cloned Object: Prototype{name='Alice', age=25}
Objects are different: true
5.2 深拷贝示例
class Address implements Cloneable {private String city;private String country;public Address(String city, String country) {this.city = city;this.country = country;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();  // 浅拷贝}@Overridepublic String toString() {return "Address{city='" + city + "', country='" + country + "'}";}
}class Person implements Cloneable {private String name;private int age;private Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {// 深拷贝: 克隆引用类型字段Person cloned = (Person) super.clone();cloned.address = (Address) address.clone();  // 深拷贝 Address 对象return cloned;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";}
}public class DeepCopyDemo {public static void main(String[] args) {try {// 创建原型对象Address address = new Address("New York", "USA");Person person1 = new Person("John", 30, address);System.out.println("Original: " + person1);// 克隆对象Person person2 = (Person) person1.clone();System.out.println("Cloned: " + person2);// 修改原始对象中的地址,不影响克隆对象中的地址address.city = "Los Angeles";System.out.println("After modifying address:");System.out.println("Original: " + person1);System.out.println("Cloned: " + person2);} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}

输出:

Original: Person{name='John', age=30, address=Address{city='New York', country='USA'}}
Cloned: Person{name='John', age=30, address=Address{city='New York', country='USA'}}
After modifying address:
Original: Person{name='John', age=30, address=Address{city='Los Angeles', country='USA'}}
Cloned: Person{name='John', age=30, address=Address{city='New York', country='USA'}}

6. 原型模式的优点

  • 性能优化:当创建对象代价较高时,克隆可以比通过构造函数创建新对象更加高效。
  • 动态创建对象:原型模式允许在运行时动态地创建对象,而不需要知道具体的类或实现。
  • 减少子类数目:避免了频繁的使用子类去生成对象,通过克隆可以生成对象的不同版本。

7. 原型模式的缺点

  • 深拷贝复杂:如果对象中有复杂的嵌套对象或循环引用,深拷贝的实现会非常复杂,需要逐层克隆每个引用的对象。
  • 依赖于具体的实现:克隆对象需要依赖类的 clone() 方法,可能会限制类的灵活性。

8. 原型模式的应用场景

  • 资源消耗大的对象创建:比如对象创建需要读取数据库、大量计算或需要访问网络资源时,可以使用原型模式进行克隆操作。
  • 重复创建相似对象:在某些系统中,需要频繁创建内容相似的对象,使用原型模式可以节省时间。
  • 不可变对象的场景:某些情况下,创建后不可修改的对象,原型模式可以保证对象的唯一性和一致性。

9. 总结

原型模式是一种有效的设计模式,适用于创建开销较大的对象。通过 clone() 方法,可以快速创建相同或类似的对象,减少创建新对象的成本。同时,它支持浅拷贝和深拷贝的灵活实现,在复杂的对象克隆场景下,深拷贝需要特别的设计。

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

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

相关文章

sm3填充

完成下面任务(10分) 1. 使用 OpenSSL 生成长度为70字节的随机数,最后添加“你的8位学号姓名首字母”的 ASCII 码,得到HEX字符串S1,提交S1。(4 分) [wzyLAPTOP-PRC71A0C ~]$ openssl rand -hex…

QT-使用QSS美化UI界面

一、QSS简介: Qt Style Sheet:Qt样式表,用来自定义控件外观的一种机制,可以把他类比成CSS(CSS主要功能与最终目的都是能使界面的表现与界面的元素分离)。QSS机制使应用程序也能像web界面那样随意地改变外观…

构建后端为etcd的CoreDNS的容器集群(二)、下载最新的etcd容器镜像

在尝试获取etcd的容器的最新版本镜像时,使用latest作为tag取到的并非最新版本,本文尝试用实际最新版本的版本号进行pull,从而取到想的最新版etcd容器镜像。 一、用latest作为tag尝试下载最新etcd的镜像 1、下载镜像 [rootlocalhost opt]# …

基于vue框架的的高校消防设施管理系统06y99(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能:设备分类,设备信息,维修人员,报修信息,维修进度,院系,消防知识,培训记录,培训信息,备件信息,备件申请,派发信息,采购信息 开题报告内容 基于Vue框架的高校消防设施管理系统开题报告 一、项目背景与意义 随着高校规模的不断扩大和校园建…

OpenCV和HALCON

OpenCV和HALCON是两种广泛用于图像处理和计算机视觉的开发库,它们各有优缺点,适合不同的应用场景。以下是两者的比较: 1. 开发背景与定位 OpenCV (Open Source Computer Vision Library): 开源库,最初由Intel开发&…

视频处理-2D卷积核处理3D时序

2D卷积核处理3D(时序)数据_pseudoconv3d-CSDN博客

【EmbeddedGUI】PFB设计说明

PFB设计说明 背景介绍 一般来说,要实现屏幕显示,就是向特定像素点写入颜色值,最简单的办法就是直接通过SPI接口,向显示器芯片的特定缓存地址,写入像素点。一般来说,显示器芯片会提供2个基本操作API&#…

qt QNetworkProxy详解

一、概述 QNetworkProxy通过设置代理类型、主机、端口和认证信息,可以使应用程序的所有网络请求通过代理服务器进行。它支持为Qt网络类(如QAbstractSocket、QTcpSocket、QUdpSocket、QTcpServer、QNetworkAccessManager等)配置网络层代理支持…

数据仓库基础概念

数据仓库 概念 数据仓库(Data Warehouse, DW)是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合。它是为满足企业决策分析需求而设计的。 面向主题:数据仓库围绕特定的主题组织数据,例如“销售”或“人力资源”&am…

springboot自动初始化表结构及其数据

1.通过配置文件进行初始化 mode:控制 SQL 初始化的模式,取值可以是: never:禁用初始化。embedded:仅在嵌入式数据库中初始化。always:每次应用启动时都初始化。 spring:sql:init:platform: mysqlmode: a…

HarmonyOS NEXT开发实战:实现高效下拉刷新与上拉加载组件(二)刷新核心逻辑与空页面集成

前言: 在上一篇文章中,我们深入探讨了如何在HarmonyOS中实现一个功能完备的空页面组件。现在,我们将进入下拉刷新和上拉加载功能的核心逻辑实现。这不仅仅是技术实现,更是对用户体验的深刻理解。本文将详细介绍如何将空页面与下拉刷新、上拉加载逻辑相结合,打造一个既高效…

学成在线实战

#1024程序员节|征文# 一、Bug修改 在实战之前,老师留了一个bug,这个bug出现的原因是因为在查询课程计划时,使用的是Inner join查询,所以当章节下面没有小节的时候,是查不出来数据的,只需要将其…

PHP企业门店订货通进销存系统小程序源码

订货通进销存系统,企业运营好帮手! 📦 开篇:告别繁琐,企业运营新选择 嘿,各位企业主和创业者们!今天我要给大家介绍一款超实用的企业运营神器——“订货通进销存系统”。在这个数字化时代&…

YOLOv5_DeepSORT实现电动自行车头盔佩戴检测系统

获取更多完整项目代码数据集,点此加入免费社区群 : 首页-置顶必看 文档说明 本文档是毕业设计——基于深度学习的电动自行车头盔佩戴检测系统的开发环境配置说明文档,该文档包括运行环境说明以及基本环境配置两大部分。在程序运行前请认真查…

零售行业的数字化营销转型之路

一方面,市场竞争激烈,电商平台、新兴品牌和跨界对手带来巨大压力。另一方面,消费者需求变化迅速,更加追求个性化、多元化和便捷化的购物体验,同时传统零售企业还面临着高成本压力,如租金、人力和库存等。 然…

Rsync数据复制/备份服务应用

文章目录 1. rsync概述1.1 什么是Rsync1.2 rsync的功能1.3 rsync 的功能特性1.4 Rsync 增量复制原理1.5 生产场景架构集群备份方案 2. Rsync工作方式介绍与实践2.1 本地数据传输模式2.1.1 本地数据传输模式语法2.1.2 本地数据传输模式实践 2.2 远程Shell 数据传输模式2.2.1 远程…

WSL(Ubuntu20.04)编译和安装DPDK

编译和安装DPDK DPDK可以使用工具meson和ninja在您的系统上进行配置、构建和安装。 DPDK配置 要配置DPDK构建,请使用: meson setup build --prefix/home/xx/dpdk19.11xxxx:~/dpdk-stable-19.11.14/$ meson setup build Message:Content Skipped libs…

React与TypeScript

React创建项目方式 react脚手架:create-react-app 项目名 --template typescript基于vite创建项目:npm init vitelatest 项目名 – --template react-ts useState自动推导 通常React会根据传入useState的默认值来自动推导类型,不需要显示标…

数据结构练习题5(链表和栈)

1环形链表 II 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测…

vue实现富文本编辑器上传(粘贴)图片 + 文字

vue实现富文本编辑器上传(粘贴)图片 文字 1.安装插件 npm install vue-quill-editor -s2.在使用vue-quill-editor富文本的时候,对于图片的处理经常是将图片转换成base64,再上传数据库,但是base64不好存储。 原理&a…