:以 java-design-patterns 仓库为例掌握对象克隆的高效实例化)
示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载原型模式Prototype Pattern是 GoF 四大创建型设计模式之一其核心思想是通过克隆一个原型实例来创建新对象而非每次都用new关键字从头构造。本文以 java-design-patterns 仓库中的 prototype 模块 为完整案例系统讲解原型模式在 Java 中的推荐实现方式、源码级调用链、适用场景与权衡取舍帮助你在实际项目中用克隆机制轻松复制复杂对象、降低创建成本。模式定位Clone 的意图与别名在 java-design-patterns 仓库中原型模式归属于创建型Creational类别其别名即Clone。模式的意图非常明确使用一个原型实例来指定要创建的对象种类并通过克隆该原型实例来创建新实例。这与仓库中 App.java 的类注释相互印证原型模式用于当待创建对象的类型由一个原型实例决定时克隆该原型以产生新对象其目标是避免在客户端应用中为每种产品都编写对应的创建器子类如抽象工厂模式那样同时规避用new关键字创建对象所带来的固有开销。现实世界类比设想一家定制家具公司它不会在每次下单时从头制作一件家具而是为最受欢迎的款式保留原型。客户下单某一设计时公司直接克隆对应原型并做必要定制。因为基础结构与设计细节已经就位公司能以一致的品质快速交付订单——这正是软件世界中原型 克隆机制的直观写照。用一句话概括就是基于一个已有对象通过克隆来创建新对象。Wikipedia 对此的定义同样简洁原型模式是一种创建型设计模式当待创建对象的类型由一个原型实例决定时通过克隆该原型来产生新对象。模式结构总览序列图如上图所示原型模式的典型交互流程是客户端向原型对象发起复制请求原型通过克隆机制返回一个状态相同的新实例客户端随后可对新实例做进一步定制整个过程对客户端隐藏了对象构造的内部复杂性。Java 实现示例从 Prototype 基类到具体原型在 Java 中原型模式的推荐做法是先定义一个带克隆方法的接口或抽象基类再由具体原型类继承/实现它。本仓库的实现正是这一思路的范本。第一步定义原型基类public abstract class PrototypeT implements Cloneable { SneakyThrows public T copy() { return (T) super.clone(); } }对应源码见 Prototype.java第 32–39 行。要点解读基类实现了Cloneable接口——这是 Java 原生Object.clone()能够正常执行而不抛CloneNotSupportedException的前提copy()内部直接调用super.clone()即Object.clone()的浅拷贝语义通过泛型T把返回类型收窄到具体原型类型调用方无需再强转SneakyThrowsLombok 注解把CloneNotSupportedException的声明吞掉让克隆调用代码更简洁。源码注释还明确指出该方法返回本对象的浅拷贝若对象不可克隆则返回 null。第二步建立产品类层级示例包含一组生物creature类层级。以Beast野兽与OrcBeast兽人野兽为例EqualsAndHashCode(callSuper false) NoArgsConstructor public abstract class Beast extends PrototypeBeast { public Beast(Beast source) {} }EqualsAndHashCode(callSuper false) RequiredArgsConstructor public class OrcBeast extends Beast { private final String weapon; public OrcBeast(OrcBeast orcBeast) { super(orcBeast); this.weapon orcBeast.weapon; } Override public String toString() { return Orcish wolf attacks with weapon; } }对应源码见 Beast.java 与 OrcBeast.java。可以观察到仓库实现的两个设计细节抽象基类持有两种构造方式NoArgsConstructor生成的无参构造供从零创建原型使用带source参数的拷贝构造供由已有原型复制字段使用具体类提供同名拷贝构造OrcBeast(OrcBeast orcBeast)显式地把weapon字段从源对象复制到新对象。虽然本示例的copy()走的是Object.clone()浅拷贝但这些拷贝构造展示了另一种实现克隆的常见路径——当克隆逻辑需要深度复制或额外定制时可以改由拷贝构造手工完成。完整的类层级还包括Mage法师与Warlord warlord统帅/战将并有精灵Elf与兽人Orc两个种族的具体实现ElfMage、OrcMage、ElfWarlord、OrcWarlord、ElfBeast、OrcBeast。其中ElfMage持有helpType字段toString()输出形如Elven mage helps in cookingOrcMage、OrcWarlord持有weapon字段输出形如Orcish mage attacks with axeElfBeast输出Elven eagle helps in ...OrcBeast输出Orcish wolf attacks with ...。以ElfMage为例ElfMage.java 同样采用RequiredArgsConstructor生成带参构造 手工拷贝构造复制 helpType的组合模式。三个抽象基类 Mage.java、Warlord.java、Beast.java 结构完全对称都继承自PrototypeT。第三步用工厂对客户端隐藏克隆细节要充分发挥原型模式的价值还需要一个生产不同种类生物的工厂。仓库提供了HeroFactory接口与HeroFactoryImpl实现public interface HeroFactory { Mage createMage(); Warlord createWarlord(); Beast createBeast(); }RequiredArgsConstructor public class HeroFactoryImpl implements HeroFactory { private final Mage mage; private final Warlord warlord; private final Beast beast; public Mage createMage() { return mage.copy(); } public Warlord createWarlord() { return warlord.copy(); } public Beast createBeast() { return beast.copy(); } }对应源码见 HeroFactory.java 与 HeroFactoryImpl.java。这里的设计值得留意原型以构造参数注入RequiredArgsConstructor让工厂在构造时接收三个原型实例一个 Mage、一个 Warlord、一个 Beast工厂本身不关心具体种族只负责复制原型创建方法全部委托给copy()createMage()返回mage.copy()其余方法同理。这正印证了 App.java 类注释中的描述——工厂的原型对象以构造参数形式给出。第四步完整运行示例App.java 的main方法展示了完整的实战流程public static void main(String[] args) { var factory new HeroFactoryImpl( new ElfMage(cooking), new ElfWarlord(cleaning), new ElfBeast(protecting) ); var mage factory.createMage(); var warlord factory.createWarlord(); var beast factory.createBeast(); LOGGER.info(mage.toString()); LOGGER.info(warlord.toString()); LOGGER.info(beast.toString()); factory new HeroFactoryImpl( new OrcMage(axe), new OrcWarlord(sword), new OrcBeast(laser) ); mage factory.createMage(); warlord factory.createWarlord(); beast factory.createBeast(); LOGGER.info(mage.toString()); LOGGER.info(warlord.toString()); LOGGER.info(beast.toString()); }运行该示例控制台输出如下08:36:19.012 [main] INFO com.iluwatar.prototype.App -- Elven mage helps in cooking 08:36:19.013 [main] INFO com.iluwatar.prototype.App -- Elven warlord helps in cleaning 08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Elven eagle helps in protecting 08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish mage attacks with axe 08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish warlord attacks with sword 08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish wolf attacks with laser从输出可以看到两次调用完全相同的createMage()/createWarlord()/createBeast()却分别产出了精灵族与兽人族的不同实例——区别仅在于注入工厂的原型对象不同。这正是原型模式由原型实例决定创建类型的直观体现。测试如何验证克隆语义仓库还提供了针对性的单元测试见 PrototypeTest.java。测试通过参数化方式覆盖全部 6 个具体原型类每个用例断言三件事toString()输出与期望一致如new OrcBeast(axe)对应Orcish wolf attacks with axecopy()返回的克隆对象assertNotNull非空克隆对象与原对象assertNotSame不是同一个引用即确实产生了新实例。其中assertNotSame正是验证原型模式核心语义的关键copy()必须返回一个全新的对象实例而非原对象的引用。测试数据同时印证了类结构与toString()行为——例如ElfBeast(cooking)输出Elven eagle helps in cooking。何时使用原型模式根据仓库文档并结合模式特性以下场景适合引入原型模式待实例化的类在运行时才确定例如通过动态加载dynamic loading方式获得具体类希望避免建立与产品类层级平行的工厂类层级——原型模式用注入原型 克隆替代了每个产品对应一个工厂子类的做法类的实例只存在少数几种状态组合更便捷的做法是预先安装相应数量的原型需要时直接克隆而不是每次手工new并设置状态对象创建成本远高于克隆成本当构造过程涉及昂贵的初始化数据库连接、IO、复杂计算时克隆已有实例能显著节省开销在运行时才知道要实例化的具体类客户端不应直接依赖具体类名。真实世界应用原型模式在 Java 生态与工业界有广泛实践Java 原生Object.clone()方法是原型模式的经典实现本仓库的Prototype.copy()正是对它的一层薄封装GUI 库常用原型来创建按钮、窗口、控件等构件通过克隆模板控件快速生成同类组件游戏开发中创建多个属性相近的对象例如大批量生成属性相似的敌人角色时克隆比逐字段构造更高效。优点与权衡优点隐藏实例化新对象的复杂性客户端只需调用copy()无需了解构造细节减少类的数量不需要为每个产品类型单独编写工厂子类支持运行时动态增删对象原型集合可随运行状态扩展新增一种原型即可产出新类型对象。权衡需要实现克隆机制可能较为复杂Cloneable的浅拷贝语义容易踩坑字段为引用类型时需格外小心深拷贝实现难度高尤其当类拥有复杂对象图、存在循环引用时正确实现深克隆很困难本仓库示例走浅拷贝路径正是为了保持示例的简洁。与相关模式的关联Abstract Factory抽象工厂两者都涉及对象创建但原型模式通过克隆原型实例创建对象抽象工厂则通过工厂方法创建对象Singleton单例单例若允许克隆其唯一实例也可借助原型模式来产生新实例Composite组合原型常被用于组合结构中以支持组件树的动态创建。小结原型模式是创建型模式家族中最经济的一员当对象构造昂贵、类型在运行时才确定、或希望避免工厂类层级膨胀时克隆一个原型即可获得全新实例。java-design-patterns 仓库的 prototype 模块 用抽象基类PrototypeT 具体原型 原型工厂HeroFactoryImpl三层结构完整展示了从克隆基类到运行时产出不同种族生物的端到端实现配合 PrototypeTest.java 中克隆结果非同一引用的断言帮助你准确理解并正确落地这一模式。若需深入对比可继续研读仓库中 abstract-factory、singleton 与 composite 模块的实现。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐Java 原型模式Prototype Pattern深入解析基于 java-design-patterns 仓库的克隆式对象创建实战Java 原型模式Prototype Pattern深入解析基于 java design patterns 仓库的克隆式对象创建实战 导读 原型模式Pr示例工程教程深入解析 Java 设计模式之扩展对象模式Extension Objects Pattern以 java-design-patterns 仓库为实战范本深入解析 Java 设计模式之扩展对象模式Extension Objects Pattern以 java design patterns 仓库为实战范本示例工程教程深入解析 Java 设计模式之享元模式Flyweight以 java-design-patterns 仓库的炼金术商店为例深入解析 Java 设计模式之享元模式Flyweight以 java design patterns 仓库的炼金术商店为例 享元模式Flyweight示例工程教程上一篇Shairport Sync中的日志聚合查询权限控制实现下一篇深度解析Obsidian Web Clipper高效构建个人知识管理系统的浏览器扩展架构创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考