原型模式详解

以下是一个结合原型模式解决实际开发问题的Java实现案例,涵盖深拷贝实现、性能优化、动态配置克隆等场景需求,附带逐行中文注释:

场景描述

实现一个可复用的游戏角色模板系统,需满足:
快速克隆:避免重复执行角色初始化(如加载3D模型、读取配置文件)
深度克隆:确保克隆对象与原对象完全独立(包括嵌套对象)
动态修改:克隆后允许局部修改属性(如武器、皮肤)
性能优化:避免重复IO操作(如模型加载)

完整代码实现

import java.io.*;/*** 游戏角色原型(实现Cloneable接口)*/
class GameCharacter implements Cloneable, Serializable {private String name;private Weapon weapon;  // 武器对象(自定义类)private byte[] model3D; // 3D模型数据(模拟大对象)public GameCharacter(String name, String modelPath) {this.name = name;load3DModel(modelPath); // 模拟耗时IO操作this.weapon = new Weapon("默认武器"); // 初始化默认武器}// 模拟从文件加载3D模型(耗时操作)private void load3DModel(String path) {System.out.println("正在加载模型:" + path);// 假设此处读取文件到byte[]this.model3D = new byte[1024 * 1024]; // 模拟1MB模型数据}/*** 浅拷贝实现(不推荐,拷贝引用,原对象变化,拷贝对象也会变化,经典八股问题之一)*/@Overridepublic GameCharacter clone() throws CloneNotSupportedException {return (GameCharacter) super.clone();}/*** 深拷贝实现(通过序列化)*/public GameCharacter deepClone() {ByteArrayOutputStream bos;ObjectOutputStream oos;ByteArrayInputStream bis;ObjectInputStream ois;try {// 将对象写入流,这里需要显式关闭,final关闭,也可以使用try-with-resourcesbos = new ByteArrayOutputStream();oos = new ObjectOutputStream(bos);oos.writeObject(this);// 从流中读取对象,这里需要显式关闭bis = new ByteArrayInputStream(bos.toByteArray());ois = new ObjectInputStream(bis);return (GameCharacter) ois.readObject();} catch (IOException | ClassNotFoundException e) {throw new RuntimeException("克隆失败", e);} finally {//..关闭流;}}// 修改武器(测试用)public void setWeapon(Weapon weapon) {this.weapon = weapon;}// 显示角色信息public void showInfo() {System.out.printf("角色:%s | 武器:%s | 模型哈希:%d%n",name, weapon.getName(), model3D.hashCode());}// 武器类(必须实现Serializable)static class Weapon implements Serializable {private String name;public Weapon(String name) { this.name = name; }public String getName() { return name; }}
}/*** 原型管理器(存储常用原型)*/
class PrototypeManager {private static final java.util.Map<String, GameCharacter> prototypes = new java.util.HashMap<>();// 预加载原型static {prototypes.put("warrior", new GameCharacter("战士", "models/warrior.obj"));prototypes.put("mage", new GameCharacter("法师", "models/mage.obj"));}// 获取原型副本public static GameCharacter getCharacter(String type) {GameCharacter proto = prototypes.get(type);if (proto == null) throw new IllegalArgumentException("未知角色类型");return proto.deepClone(); // 返回深拷贝副本}
}// 测试代码
public class PrototypeDemo {public static void main(String[] args) throws Exception {// 1. 基础克隆测试GameCharacter orig = new GameCharacter("原型角色", "models/base.obj");orig.setWeapon(new GameCharacter.Weapon("默认武器"));GameCharacter shallowCopy = orig.clone();GameCharacter deepCopy = orig.deepClone();System.out.println("-- 浅拷贝 vs 深拷贝 --");orig.showInfo();          // 角色:原型角色 | 武器:默认武器 | 模型哈希shallowCopy.showInfo();   // 模型哈希相同(共享同一模型数据)deepCopy.showInfo();      // 模型哈希不同(独立数据),且只会拷贝引用// 2. 修改武器测试shallowCopy.weapon.name = "新武器";deepCopy.weapon.name = "超级武器";System.out.println("\n-- 武器修改后 --");//这里由于浅拷贝的对象改变了值,武器对象在两个对象里面属于同一个引用,原始对象的武器发生改变//深拷贝就会改变引用,不会影响原始对象,深拷贝就可以复制一个全新对象,所有均不影响原始对象orig.showInfo();          // 武器:新武器 模型哈希:558638686shallowCopy.showInfo();   // 武器:新武器 模型哈希:558638686deepCopy.showInfo();      // 武器:超级武器 模型哈希:1268447657// 3. 使用原型管理器GameCharacter warrior1 = PrototypeManager.getCharacter("warrior");GameCharacter warrior2 = PrototypeManager.getCharacter("warrior");System.out.println("\n-- 原型管理器生成对象 --");System.out.println("是否为同一模型:" + (warrior1.hashCode() == warrior2.hashCode())); // false(深拷贝)}
}

真实场景问题

1.当系统中需要创建大量相似对象,且这些对象之间的差异较小时,可以使用原型模式来复制一个已有对象,然后根据需要修改差异部分,减少对象创建的开销。
2.在数据库中获取的数据对象可能需要在业务逻辑中进行多次使用,而不希望频繁地从数据库中读取相同的数据。使用原型模式可以在第一次获取数据时创建原型对象,后续需要相似数据时直接复制原型对象,减少数据库交互。
3.当对象的创建过程较为复杂,包含多个步骤或依赖关系时,可以通过原型模式创建一个已经初始化的对象,然后在需要时进行复制,避免重复的初始化过程。
4.如果系统中有一些配置对象,这些对象的配置信息可能在运行时动态发生变化,使用原型模式可以在初始状态下创建一个配置对象的原型,然后根据需要进行复制并动态修改配置信息。

一句话总结

原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制已有对象来创建新对象,而不需要使用显式的构造函数调用来创建。建议学习原型可以使用debug看一下java对象地址或者对象序号。

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

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

相关文章

Git使用和原理(3)

1.远程操作 1.1分布式版本控制系统 我们⽬前所说的所有内容&#xff08;⼯作区&#xff0c;暂存区&#xff0c;版本库等等&#xff09;&#xff0c;都是在本地&#xff01;也就是在你的笔记本或者 计算机上。⽽我们的 Git 其实是分布式版本控制系统&#xff01;什么意思呢&a…

ssm框架之mybatis框架讲解

1&#xff0c;Mybatis 1.1 Mybatis概述 1.1.1 Mybatis概念 MyBatis 是一款优秀的持久层框架&#xff0c;用于简化 JDBC 开发 MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code&#xff0c;并且改名为MyBatis 。2…

方法之笔,驭繁于简.绘场景之魂——方法论引领支撑透明化项目之航

关注作者 项目建设中痛难点剖析&#xff1a; 01 项目策划有缺失&#xff0c;目标风险难管控 ①目标设定不合理&#xff0c;由于项目移交交底不充分&#xff0c;造成项目建设目标与前期立项论证偏差过大&#xff0c;达不到建设预期&#xff1b; ②风险评估不足&#xff0c;未…

【Apache Storm】

一、Storm简介 1、概述 官网地址&#xff1a;https://storm.apache.org/index.html Apache Storm 是一个开源的、分布式的实时计算系统&#xff0c;专为处理流式数据而设计。它能够处理大量数据流并在极低的延迟下提供实时的结果。相比于传统的批处理系统&#xff0c;Storm 具…

【力扣刷题实战】无重复的最长字串

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 力扣题目&#xff1a; 无重复的最长字串 题目描述 解题思路 问题理解 算法选择 具体思路 解题要点 完整代码&#xff08;C&#xff09; 兄弟们共勉 &#xff01;&#xff01;&#xff01; 每篇前言 博客主页&#x…

联想扬天M590台式机开机卡LOGO不引导故障维修案例分享

故障描述&#xff1a; 用户送修联想扬天M590台式机到站端维修&#xff0c;说是开机不能正常进系统&#xff1b;站端检测开机后卡LOGO、无法加载引导系统&#xff1b; 故障检修&#xff1a; 插拔内存、插拔硬盘&#xff0c;更换内存、更换硬盘均不能解决此故障&#xff1b;调试…

C++刷题(三):string

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人的基础算法学习以及刷题记录&#xff0c;使用语言为C。 每道题我会给出LeetCode上的题号&#xff08;如果有题号&#xff09;&#xff0c;题目&#xff0c;以及最后通过的代码。没有题号的题目大多来自牛客网。对于题目的…

PosterRender 实现微信下程序 分享商品生成海报

PosterRender 是什么 PosterRender 是一种专注于生成高质量海报图像的技术或工具&#xff0c;常用于生成静态图片&#xff0c;特别是适合用于营销、宣传和展示的图形设计。它通常用于在服务端或客户端渲染复杂的图像&#xff0c;包括文字、图形、图标、背景等&#xff0c;生成…

Spring Cloud Stream - 构建高可靠消息驱动与事件溯源架构

一、引言 在分布式系统中&#xff0c;传统的 REST 调用模式往往导致耦合&#xff0c;难以满足高并发和异步解耦的需求。消息驱动架构&#xff08;EDA, Event-Driven Architecture&#xff09;通过异步通信、事件溯源等模式&#xff0c;提高了系统的扩展性与可观测性。 作为 S…

Houdini制作非均匀细分的柱体

近期看见一非均匀细分的做法&#xff0c;觉得不错将其拆开以笔记分享。效果如下&#xff1a; 1.创建Geometry节点&#xff0c;并在该节点内部创建line节点样条线&#xff0c;设置合适长度并添加resample节点。 2.此时若无法看见顶点与顶点编号显示&#xff0c;可按快捷键D&am…

C# Unity 唐老狮 No.10 模拟面试题

本文章不作任何商业用途 仅作学习与交流 安利唐老狮与其他老师合作的网站,内有大量免费资源和优质付费资源,我入门就是看唐老师的课程 打好坚实的基础非常非常重要: Unity课程 - 游习堂 - 唐老狮创立的游戏开发在线学习平台 - Powered By EduSoho C# 1. 内存中&#xff0c;堆和…

Nuxt2 vue 给特定的页面 body 设置 background 不影响其他页面

首先认识一下 BODY_ATTRS 他可以在页面单独设置 head () {return {bodyAttrs: {form: form-body}};},设置完效果是只有这个页面会加上 接下来在APP.vue中添加样式

拥抱健康养生,开启活力生活

在快节奏的现代社会&#xff0c;健康养生不再是一句口号&#xff0c;而是我们对高品质生活的追求。它贯穿于日常的点点滴滴&#xff0c;对我们的身心状态有着深远影响。 饮食养生是基础。秉持均衡原则&#xff0c;每日的餐盘应是色彩斑斓的。新鲜蔬菜富含维生素与膳食纤维&…

Excel(函数篇):COUNTIF与CONUTIFS函数、SUMIF与SUMIFS函数、ROUND函数、MATCH与INDEX函数、混合引用与条件格式

目录 COUNTIF和COUNTIFS函数COUNTIF函数COUNTIFS函数SUMIF和SUMIFS函数SUMIF函数SUMIFS函数SUMIFS函数与控件实现动态年月汇总ROUND、ROUNDUP、ROUNDDOWN函数单元格混合引用条件格式与公式,标记整行数据MATCH和INDEX函数COUNTIF和COUNTIFS函数 COUNTIF函数 统计下“苏州”出现…

深入了解Linux —— git三板斧

版本控制器git 为了我们方便管理不同版本的文件&#xff0c;就有了版本控制器&#xff1b; 所谓的版本控制器&#xff0c;就是能够了解到一个文件的历史记录&#xff08;修改记录&#xff09;&#xff1b;简单来说就是记录每一次的改动和版本迭代的一个管理系统&#xff0c;同…

笔记本电脑关不了机是怎么回事 这有解决方法

在快节奏的现代生活中&#xff0c;笔记本电脑已成为我们工作、学习和娱乐的得力助手。在使用电脑的过程中&#xff0c;笔记本电脑突然关不了机了&#xff0c;怎么回事&#xff1f;下面驱动人生就来讲一讲笔记本电脑不能正常关机的解决方法&#xff0c;有需要的可以来看看。 一、…

Unity打包的WebGL包打不开问题解决方案,以及WebGL包嵌入至Vue2中的步骤

问题描述 在做项目时&#xff0c;需要将Unity做出的场景与Vue2结合&#xff0c;遇到了一些问题&#xff0c;在网上搜了很多解决方案&#xff0c;最终根据下面这篇博客的内容成功解决。解决方案 https://blog.csdn.net/m0_56308072/article/details/135502566注意事项 &#xff…

TW-SOA中的ASE:建模和实验

----翻译自G. Talli , M.J. Adams于2003年发表的论文 摘要 我们提出了一个行波半导体光放大器 &#xff08;TW-SOA&#xff09; 中放大自发辐射 &#xff08;ASE&#xff09; 的模型。所提出的模型考虑了整个 ASE 频谱的传播&#xff0c;还考虑了信号和 ASE 引起的饱和效应。使…

AI编程方法案例:PageRank算法实现

一、算法简单说明 PageRank算法是一种常见的网络权值迭代算法&#xff0c;主要用于诸如互联网网页的质量测度。基本计算原理是根据网页自身的链出将原始权值进行扩散&#xff0c;并通过多轮迭代获得稳定的收敛值来表征网页自身的最终权值。基本计算公式为&#xff1a; 其中R(u…

基于香橙派 KunpengPro学习CANN(3)——pytorch 模型迁移

通用模型迁移适配可以分为四个阶段&#xff1a;迁移分析、迁移适配、精度调试与性能调优。 迁移分析 迁移支持度分析&#xff1a; 准备NPU环境&#xff0c;获取模型的源码、权重和数据集等文件&#xff1b;使用迁移分析工具采集目标网络中的模型/算子清单&#xff0c;识别第三方…