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

原型模式详细介绍和代码实现

🎯 设计模式专栏,持续更新中, 欢迎订阅:JAVA实现设计模式
🛠️ 希望小伙伴们一键三连,有问题私信都会回复,或者在评论区直接发言

Java实现原型模式

介绍: 原型模式(Prototype Pattern)是一种创建型设计模式,允许通过复制已有对象来创建新对象,而不需要依赖其具体类。这种模式的关键在于克隆现有对象,而不是通过直接实例化新对象,从而避免重复的复杂对象构建过程。

🎯 案例场景:

假设我们在开发一个游戏角色系统,每个角色都有不同的属性,比如力量、敏捷和智力。创建一个新角色需要耗费大量的计算资源(如生成外貌、装备等)。如果我们想要快速创建一个与现有角色相似的新角色,只需要在原有角色基础上进行微调,而不重新生成所有属性。

我们可以使用原型模式,通过复制已有角色对象,再对其进行调整,来生成新的角色。

原型模式的核心步骤:

  1. Prototype 接口:定义 clone() 方法,所有需要被复制的对象实现该接口。
  2. 具体原型类:实现 clone() 方法,用于创建对象的副本。
  3. 客户端代码:通过调用 clone() 方法来复制已有对象。

🧑‍💻 Java代码实现:

在这里插入图片描述

import java.util.HashMap;
import java.util.Map;// 1. 定义原型接口 Prototype
interface GameCharacter extends Cloneable {GameCharacter clone();void display();
}// 2. 具体的角色类实现原型接口
class Warrior implements GameCharacter {private String name;private int strength;private int agility;private int intelligence;public Warrior(String name, int strength, int agility, int intelligence) {this.name = name;this.strength = strength;this.agility = agility;this.intelligence = intelligence;}// 实现 clone 方法@Overridepublic Warrior clone() {try {return (Warrior) super.clone();  // 调用 Object 类的 clone 方法} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}// 展示角色信息@Overridepublic void display() {System.out.println("Warrior [Name: " + name + ", Strength: " + strength +", Agility: " + agility + ", Intelligence: " + intelligence + "]");}
}// 3. 客户端代码,使用原型模式
public class PrototypePatternDemo {public static void main(String[] args) {// 创建一个原始的角色Warrior originalWarrior = new Warrior("Arthas", 80, 50, 30);originalWarrior.display();// 使用克隆方法复制角色Warrior clonedWarrior = originalWarrior.clone();// 修改克隆对象的某些属性clonedWarrior.display();// 现在,原始角色和克隆角色的内存地址不同,但属性相同System.out.println("Original Warrior HashCode: " + originalWarrior.hashCode());System.out.println("Cloned Warrior HashCode: " + clonedWarrior.hashCode());}
}

📋 解释:

  1. GameCharacter 接口:定义了 clone() 方法,表示所有实现这个接口的类都可以被克隆。
  2. Warrior:实现了 GameCharacter 接口,并通过 super.clone() 进行浅克隆。这个方法通过复制对象的当前状态来创建一个新实例。
  3. 客户端代码:首先创建了一个 Warrior 对象 originalWarrior,并使用其 clone() 方法创建了一个副本 clonedWarrior。然后可以自由修改克隆对象的属性,而不影响原始对象。

🌟 应用场景:

  1. 对象创建开销大,不希望每次都通过构造函数创建。
  2. 需要保存对象的初始状态,以便在不同地方进行修改和操作。
  3. 游戏开发中,需要频繁创建相似但稍有不同的角色或物品。

深拷贝和浅拷贝

浅拷贝:复制对象时,只复制对象的基本属性引用类型的引用。即如果对象的属性是引用类型(如数组、对象),浅拷贝只会复制这些引用,而不是引用所指向的实际对象。因此,拷贝后的对象和原始对象共享这些引用类型的数据,修改引用类型的内容会影响原始对象。

深拷贝:不仅会复制对象的基本属性,还会递归地复制引用类型所指向的对象,即引用对象也会完全复制成一个新的副本。这样,拷贝后的对象与原始对象完全独立,修改拷贝对象的引用类型内容,不会影响原始对象。

🌟 案例解释:

假设我们有一个 Person 类,里面包含基本类型属性 name 和引用类型 address

1. 浅拷贝示例:

浅拷贝只复制基本属性和引用对象的引用,不复制引用对象本身。

class Address {String city;public Address(String city) {this.city = city;}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}// 浅拷贝@Overridepublic Person clone() {try {return (Person) super.clone();  // 调用 Object 的 clone 方法} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}public void display() {System.out.println("Name: " + name + ", City: " + address.city);}
}public class ShallowCopyDemo {public static void main(String[] args) {Address address = new Address("New York");Person person1 = new Person("John", address);Person person2 = person1.clone();  // 浅拷贝// 显示原始和克隆对象person1.display();  // Name: John, City: New Yorkperson2.display();  // Name: John, City: New York// 修改克隆对象的 addressperson2.address.city = "San Francisco";// 浅拷贝后,原始对象的 address 也被改变person1.display();  // Name: John, City: San Franciscoperson2.display();  // Name: John, City: San Francisco}
}

结果解释

  • person2person1 的浅拷贝。
  • person2address.city 修改为 "San Francisco" 后,person1address.city 也变成了 "San Francisco"。这是因为浅拷贝只复制了引用,两个对象共享同一个 Address 对象。
2. 深拷贝示例:

深拷贝需要复制所有对象,包括引用对象中的数据。

class Address implements Cloneable {String city;public Address(String city) {this.city = city;}@Overridepublic Address clone() {try {return (Address) super.clone();  // 克隆 Address 对象} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}// 深拷贝@Overridepublic Person clone() {try {Person clonedPerson = (Person) super.clone();clonedPerson.address = address.clone();  // 深拷贝 Addressreturn clonedPerson;} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported", e);}}public void display() {System.out.println("Name: " + name + ", City: " + address.city);}
}public class DeepCopyDemo {public static void main(String[] args) {Address address = new Address("New York");Person person1 = new Person("John", address);Person person2 = person1.clone();  // 深拷贝// 显示原始和克隆对象person1.display();  // Name: John, City: New Yorkperson2.display();  // Name: John, City: New York// 修改克隆对象的 addressperson2.address.city = "San Francisco";// 深拷贝后,原始对象的 address 未被改变person1.display();  // Name: John, City: New Yorkperson2.display();  // Name: John, City: San Francisco}
}

结果解释

  • person2person1 的深拷贝。
  • person2address.city 修改为 "San Francisco" 后,person1address.city 仍然是 "New York"。这是因为深拷贝创建了 Address 对象的独立副本,两个对象不再共享同一个引用。

🔍 关键区别总结:

  1. 浅拷贝
    • 只复制对象的基本类型属性引用的地址,不复制引用的实际内容。
    • 拷贝后的对象与原对象共享引用类型的对象。
    • 如果修改了引用类型的数据,原始对象也会受到影响。
  2. 深拷贝
    • 复制对象的所有属性,包括递归复制引用类型对象
    • 拷贝后的对象和原始对象完全独立,互不影响。
    • 修改其中一个对象的引用类型内容,不会影响另一个对象。

相关文章:

原型模式详细介绍和代码实现

🎯 设计模式专栏,持续更新中, 欢迎订阅:JAVA实现设计模式 🛠️ 希望小伙伴们一键三连,有问题私信都会回复,或者在评论区直接发言 Java实现原型模式 介绍: 原型模式(Prototype Patte…...

ArcGIS Pro SDK (十三)地图创作 5 图层样式

ArcGIS Pro SDK (十三)地图创作 5 图层样式 文章目录 ArcGIS Pro SDK (十三)地图创作 5 图层样式1 风格管理1.1 如何按名称获取项目中的样式1.2 如何创建新样式1.3 如何向项目添加样式1.4 如何从项目中删除样式1.5 如何将样式项添加到样式1.6 如何从样式中删除样式项1.7 如…...

【Python报错已解决】 Requests.exceptions.ProxyError: HTTPSConnectionPool

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…...

现在量化中普遍使用QMT和PTrade?哪家可以同时提供QMT/PTrade?

QMT的特点 全面的功能集成: QMT集成了行情显示、策略研究、交易执行和风控管理于一体,为投资者提供了一站式的量化交易解决方案。 高效的交易执行能力: 通过全内存交易实现低延迟的交易执行,单笔延时小于1ms,确保了交易…...

【计算机网络】UDP 协议详解及其网络编程应用

文章目录 一、引言二、UDP1、UDP的协议格式2、UDP 报文的解包和分用3、UDP面向数据报的特点 三、UDP输入输出四、UDP网络编程 一、引言 UDP(User Datagram Protocol,用户数据报协议)是一种网络通信协议,它属于传输层的协议。是一…...

基于ESP32S3的链接大语言模型对话模块

本实物模块从实物外观、模块组成、API申请及功能说明四部分来介绍这款基于ESP32S3的大语言模型对话模块。 1、实物外观 2、模块介绍 本硬件平台主要由三个模块组成,包括MAX9814录音模块、MAX98357音频功放模块和ESP32S3模块。如下图所示。 MAX9814录音模块&#…...

Cpp输出多字符常量警告

Cpp输出多字符常量警告 Cpp中用单引号(single quotes)表示单个字符(single character),例如a,$,用双引号(double quotes)表示字符串文本(text),例如"Hello World! " 当在一个单引号里面存在多个字符时,Cpp…...

Maven从入门到精通(二)

一、什么是pom.xml pom.xml是Maven项目的核心配置文件,它是 项目对象模型 - Project Object Model(POM)的缩写。POM定义了项目的所有属性,包括项目的名称、版本、依赖关系、构建配置等。使用pom.xml,我们可以轻松地管…...

【Kubernetes】常见面试题汇总(二十四)

目录 71.假设一家公司想要修改它的部署方法,并希望建立一个更具可扩展性和响应性的平台。您如何看待这家公司能够实现这一目标以满足客户需求? 72.考虑一家拥有非常分散的系统的跨国公司,期待解决整体代码库问题。您认为公司如何解决他们的问…...

最低成本的游戏串流方案分享 如何自己打造云电脑?

今天教大家如何最低成本实现串流 出门在外也可以随时随地游玩端游大作 硬件准备:一台电脑 手机/平板一台 软件:Gameviewer远程 为啥不用moonlight等其他软件呢 因为设置公网穿透等复杂操作对小白来说不太友好 而GameViewer从安装到使用仅需一键 对比同类…...

python运行时错误:找不到fbgemm.dll

python运行时错误:找不到fbgemm.dll 报错: OSError: [WinError 126] 找不到指定的模块。 Error loading "D:\program\py\312\Lib\site-packages\torch\lib\fbgemm.dll" or one of its dependencies. 原因是Windows下缺失:libomp140…...

给虚拟机linux系统安装交叉编译工具链

我们在电脑上写的代码编译生成的是X86架构的二进制文件,只能在X86平台上运行,而开发板是ARM架构因此需要安装交叉编译链工具,这样在电脑上写的代码交叉编译之后生成的是ARM架构的二进制文件。 绿色的字眼是与本文无关的只是这样有助于我们的…...

Redhat 7,8系(复刻系列) 一键部署Oracle21c-xe rpm

Oracle21c-xe前言 无论您是开发人员、DBA、数据科学家、教育工作者,还是仅仅对数据库感兴趣,Oracle Database Express Edition (XE) 都是理想的入门方式。它是全球企业可依赖的强大的 Oracle Database,提供简单的下载、易于使用和功能齐全的体验。您可以在任何环境中使用该…...

Web植物管理系统-下位机部分

本节主要展示上位机部分,采用BSP编程,不附带BSP中各个头文件的说明,仅仅是对main逻辑进行解释 main.c 上下位机通信 通过串口通信,有两位数据验证头(verify数组中保存对应的数据头 0xAA55) 通信格式 上位发送11字节…...

leetcode169. 多数元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入:nums [3,2,3] 输出:3 示例…...

从大脑图谱/ROI中提取BOLD信号

动机 在功能连接(Functional Connectivity,FC)构建过程中,由于FC中元素数目是节点数目的平方关系,所以在计算FC之前进行数据降维是一个常见的选择。 一般会将体素级/顶点级BOLD信号(在2mm的图像分辨率下大脑…...

Java-数据结构-优先级队列(堆)-(一) (;´д`)ゞ

文本目录: ❄️一、优先级队列: ➷ 1、概念: ❄️二、优先级队列的模拟实现: ➷ 1、堆的概念: ➷ 2、堆的性质: ➷ 3、堆的创建: ▶ 向下调整: ➷ 4、堆的插入和删除: …...

工厂模式(二):工厂方法模式

一、概念 工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。从而使得系统更加灵活。客户端可以通过调用工厂方法来创建所需的产品,而不必…...

【洛谷】P11036 【MX-X3-T3】「RiOI-4」GCD 与 LCM 问题 的题解

【洛谷】P11036 【MX-X3-T3】「RiOI-4」GCD 与 LCM 问题 的题解 题目传送门 题解 神奇构造题qaq 简化一下下题目,就是要求 a b c d gcd ⁡ ( a , b ) lcm ⁡ ( c , d ) a b c d \gcd(a, b) \operatorname{lcm}(c,d) abcdgcd(a,b)lcm(c,d) 分类讨论 …...

MyBatis系统学习(三)——动态SQL

MyBatis 是一款优秀的持久层框架,它通过 XML 或注解方式将 SQL 语句与 Java 对象映射起来。动态 SQL 是 MyBatis 中非常强大的功能之一,能够根据不同的条件动态生成 SQL 语句。动态 SQL 通过各种标签来灵活生成 SQL,从而避免了在代码中拼接 S…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理&#xff1a…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...