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

Java设计模式精讲---04原型模式

你是否遇到过这样的场景:需要创建大量结构相似、仅少数属性不同的对象(比如 100 个游戏角色,基础属性相同,仅昵称和装备有差异)?如果每次都通过new关键字从头初始化,不仅代码冗余,还会因为重复执行构造函数中的复杂逻辑(比如数据库查询、网络请求)浪费性能。

这时候,原型模式(Prototype Pattern) 就能派上用场 —— 它的核心思想是:通过复制现有对象(原型)来创建新对象,而非重新初始化,就像现实中 “复制粘贴” 文档再修改细节,既高效又省力。

一、核心概念:克隆,而非新建

原型模式的本质是 “对象克隆”,它通过让对象自身提供复制方法,将对象的创建过程从 “主动新建” 转为 “被动复制”。关键角色只有两个:

  • 原型接口(Prototype):定义克隆方法(比如 Java 中的Cloneable接口,虽然是标记接口,但约定了clone()方法);
  • 具体原型(Concrete Prototype):实现克隆方法,完成自身复制。
二、实现方式:浅克隆 vs 深克隆

克隆的核心是 “复制对象的属性”,但根据属性类型(基本类型 / 引用类型),克隆分为两种:

1. 浅克隆:只复制 “表面”

浅克隆会复制对象的基本类型属性(int、String 等),但对于引用类型属性(比如对象、集合),仅复制引用地址 —— 新对象和原对象的引用属性会指向同一个内存地址,修改其中一个会影响另一个。

Java 实现示例(基于Cloneable接口):

​
// 具体原型:游戏角色
class GameRole implements Cloneable {private String name; // 基本类型private int level;   // 基本类型private Equipment equipment; // 引用类型(装备)// 构造函数(模拟复杂初始化逻辑)public GameRole(String name, int level, Equipment equipment) {this.name = name;this.level = level;this.equipment = equipment;System.out.println("执行复杂初始化(比如加载角色模型)...");}// 实现克隆方法(浅克隆)@Overrideprotected GameRole clone() throws CloneNotSupportedException {return (GameRole) super.clone(); // Object.clone()默认是浅克隆}// getter/setter省略
}// 引用类型:装备
class Equipment {private String weapon;public Equipment(String weapon) { this.weapon = weapon; }// getter/setter省略
}// 测试浅克隆
public class PrototypeDemo {public static void main(String[] args) throws CloneNotSupportedException {// 创建原型对象(执行一次复杂初始化)Equipment equip = new Equipment("木剑");GameRole prototype = new GameRole("原型角色", 1, equip);// 克隆出3个新角色(无需重复初始化)GameRole role1 = prototype.clone();role1.setName("玩家1");GameRole role2 = prototype.clone();role2.setName("玩家2");GameRole role3 = prototype.clone();role3.setName("玩家3");// 问题:修改原型的装备,会影响所有克隆对象(因为引用同一份)prototype.getEquipment().setWeapon("铁剑");System.out.println(role1.getEquipment().getWeapon()); // 输出"铁剑"(被影响)}
}​
2. 深克隆:复制 “全部细节”

深克隆会递归复制所有属性,包括引用类型 —— 新对象和原对象的引用属性完全独立,修改互不影响。常见实现方式有两种:

  • 手动对引用类型属性递归克隆;
  • 通过序列化(将对象转成字节流再恢复)实现(更通用)。

序列化实现深克隆示例

​
import java.io.*;// 注意:需要实现Serializable接口
class GameRole implements Cloneable, Serializable {private String name;private int level;private Equipment equipment; // 引用类型也需实现Serializable// 深克隆:通过序列化public GameRole deepClone() throws IOException, ClassNotFoundException {// 1. 序列化:将对象写入字节流ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);// 2. 反序列化:从字节流恢复对象(新对象)ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (GameRole) ois.readObject();}// 其他代码省略
}// 装备类也需实现Serializable
class Equipment implements Serializable {private String weapon;// 代码省略
}// 测试深克隆
public class DeepCloneDemo {public static void main(String[] args) throws Exception {Equipment equip = new Equipment("木剑");GameRole prototype = new GameRole("原型角色", 1, equip);GameRole role1 = prototype.deepClone();role1.setName("玩家1");// 修改原型的装备,克隆对象不受影响prototype.getEquipment().setWeapon("铁剑");System.out.println(role1.getEquipment().getWeapon()); // 输出"木剑"(独立)}
}​
三、适合用原型模式的 3 类场景
  1. 对象创建成本高:如果对象构造需要大量资源(比如数据库查询、文件 IO),克隆比new更高效(比如报表系统中,批量生成结构相同、数据略有差异的报表);
  2. 需要动态生成对象:比如插件系统,无法提前知道要创建的对象类型,可通过克隆已加载的插件实例扩展功能;
  3. 避免构造函数副作用:如果构造函数中有非初始化逻辑(比如注册监听器),重复调用可能导致意外(克隆可跳过构造函数)。
四、避坑指南
  • 浅克隆可能导致 “意外共享”:如果对象包含引用类型,优先用深克隆(除非明确需要共享引用);
  • 序列化深克隆的限制:被克隆的类及所有引用类型必须实现Serializable, transient 修饰的属性不会被克隆;
  • 克隆与构造函数:Object.clone()不会调用构造函数,若初始化逻辑依赖构造函数,需在克隆后手动补充。
总结

原型模式是 “高效复制” 的代名词 —— 当你需要批量创建相似对象时,与其重复new和初始化,不如 “克隆原型 + 修改细节”。记住:浅克隆适合简单对象,深克隆适合含引用类型的复杂对象,根据场景选择即可。

http://www.dtcms.com/a/585065.html

相关文章:

  • 有哪些网站是可以做免费推广的做视频网站要多大的服务器
  • 线代强化NO1|行列式及矩阵
  • Shelly智能模块:家居科技革新之选
  • 网页Iframe读取PDF文件的参数设置
  • 电子商务网站规划与建设广州网站建设网站制作公司
  • 线性代数 - 理解 特征方程 Eigenvalue Equation定义的合理性
  • 关于新项目在PyCharm中自动构建UV环境的问题
  • jmeter 使用汇总报告查看吞吐量(QPS) 总在一个低数值上不去的解决办法
  • C++ 方向 Web 自动化测试实战:以博客系统为例,从用例到报告全流程解析
  • 东莞网站建设排名浙江省网站集约化建设
  • 《VS+Elasticsearch+Figma:开发全流程工具联动指南》
  • 代码自动生成文本小工具TextStringizerWpf
  • 旅游加盟网站建设网络营销类型
  • 【PySpark】安装测试
  • 网站建设现在主要做些什么软件开发项目实施方案
  • 信道编码的分类和总结
  • 实例:跳动的心,火柴人
  • STM32项目分享:智能窗帘(机智云)
  • web网页开发,在线%商城,电商,商品购买%系统demo,基于vscode,apache,html,css,jquery,php,mysql数据库
  • 国外免费服务器地址优速网站建设优化seo
  • jmeter 分布式压测
  • 黑马JAVAWeb-11 请求参数为数组-XML自动封装-XML手动封装-增删改查-全局异常处理-单独异常分别处理
  • 算法通关指南:数据结构和算法篇 --- 队列相关算法题》--- 1. 【模板】队列,2. 机器翻译
  • 招聘决策新变革:判断型 AI 的应用与价值
  • 缓存三大问题深度解析:穿透、击穿与雪崩
  • 如何开公司做网站百度官方营销推广平台加载中
  • Linux:make自动化和实战演练
  • Qt实战:自定义搜索跳转控件 | 附完整源码
  • nanochat大语言模型讲解一
  • Vue3:watch与watchEffect的异同