【设计模式】【创建型模式】原型模式(Prototype)
- 互联网
- 2025-08-29 17:30:02

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度++ 👍 欢迎点赞、收藏、关注,跟上我的更新节奏 🎵 当你的天空突然下了大雨,那是我在为你炸乌云
文章目录 一、入门什么是原型模式?为什么要有原型模式?如何实现原型模式? 二、原型模式在框架源码中的使用JDK 的 Object.clone()Java 集合框架中的 ArrayList.clone()Spring Framework 中的 Prototype Bean 三、总结原型模式的优点原型模式的缺点原型模式的适用场景 一、入门 什么是原型模式?原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化类。 原型模式的核心是克隆(Clone),即通过复制现有对象来创建新对象。Java 提供了 Cloneable 接口和 clone() 方法来实现对象的浅拷贝。
为什么要有原型模式? 对象创建成本高 问题:某些对象的创建过程可能非常复杂,涉及大量的计算或资源消耗。例如,数据库连接、网络请求、复杂的初始化过程等。解决方案:通过原型模式,可以直接复制现有对象,避免重复进行高成本的初始化过程。 需要动态配置对象 问题:在某些情况下,对象的配置需要在运行时动态确定,而不是在编译时确定。如果每次都需要重新创建和配置对象,会导致代码复杂且难以维护。解决方案:原型模式允许通过复制现有对象来创建新对象,并根据需要动态修改其配置。 避免子类化 问题:在某些情况下,通过继承来扩展对象的功能会导致类层次结构复杂,难以维护。解决方案:原型模式通过复制现有对象来创建新对象,而不是通过继承来扩展功能,从而简化了类层次结构。 保持对象状态 问题:在某些情况下,需要创建与现有对象状态相同的新对象。如果每次都手动复制对象的状态,会导致代码冗余且容易出错。解决方案:原型模式通过克隆现有对象来自动复制其状态,减少了手动复制状态的工作量。 如何实现原型模式?原型模式由以下角色组成:
原型接口(Prototype Interface) 定义克隆方法的接口或抽象类。在 Java 中,通常使用 Cloneable 接口来标记类支持克隆。 具体原型类(Concrete Prototype) 实现原型接口的具体类,负责实现克隆方法。通常需要重写 clone() 方法来定义具体的克隆逻辑。 客户端(Client) 使用原型对象的类,通过调用原型对象的克隆方法来创建新对象。【案例】打印身份证 假设你需要复印身份证,每次复印时,原始身份证的内容(姓名、身份证号、地址等)是固定的,但复印件的用途可能不同(如用于银行开户、办理签证等)。如果每次都重新填写身份证信息,效率很低。 原型模式解决方案:
身份证原件(原型):包含固定的个人信息。复印件(克隆对象):复制原件的内容,并根据用途添加额外信息(如用途备注)。原型接口(Cloneable 是 Java 内置接口): Prototype接口
interface Prototype extends Cloneable { Prototype clone(); }具体原型类(Concrete Prototype) IDCard类
class IDCard implements Prototype { private String name; private String idNumber; private String address; private String purpose; // 复印件的用途 public IDCard(String name, String idNumber, String address) { this.name = name; this.idNumber = idNumber; this.address = address; } public void setPurpose(String purpose) { this.purpose = purpose; } @Override public IDCard clone() { try { return (IDCard) super.clone(); // 调用 Object 的 clone() 方法 } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } @Override public String toString() { return "IDCard{" + "name='" + name + '\'' + ", idNumber='" + idNumber + '\'' + ", address='" + address + '\'' + ", purpose='" + purpose + '\'' + '}'; } }客户端
class CopyMachine { public static void main(String[] args) { // 创建身份证原件 IDCard originalIDCard = new IDCard("张三", "123456789012345678", "北京市朝阳区"); // 复印身份证用于银行开户 IDCard copyForBank = originalIDCard.clone(); copyForBank.setPurpose("银行开户"); // 复印身份证用于办理签证 IDCard copyForVisa = originalIDCard.clone(); copyForVisa.setPurpose("办理签证"); // 打印结果 System.out.println("原件: " + originalIDCard); System.out.println("银行开户复印件: " + copyForBank); System.out.println("办理签证复印件: " + copyForVisa); } } 二、原型模式在框架源码中的使用 JDK 的 Object.clone()Java 的根类 Object 提供了 clone() 方法,它是原型模式的底层实现基础。任何实现 Cloneable 接口的类都可以通过 clone() 方法创建新对象。
public class Object { protected native Object clone() throws CloneNotSupportedException; }使用约束
必须实现 Cloneable 接口:否则调用 clone() 会抛出 CloneNotSupportedException。默认是浅拷贝:需要深拷贝时,必须手动重写 clone() 方法。 Java 集合框架中的 ArrayList.clone()Java 的 ArrayList 类实现了 Cloneable 接口,其 clone() 方法通过浅拷贝快速复制一个新的列表。
ArrayList<String> original = new ArrayList<>(); original.add("A"); original.add("B"); ArrayList<String> copy = (ArrayList<String>) original.clone(); copy.add("C"); System.out.println(original); // 输出 [A, B] System.out.println(copy); // 输出 [A, B, C] 源码实现 public class ArrayList<E> implements Cloneable { // ... public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { throw new InternalError(e); } } } Spring Framework 中的 Prototype BeanSpring 框架中的 Bean 作用域(Scope)之一是 prototype,它表示每次从容器中获取 Bean 时都会创建一个新的实例。这本质上是原型模式的一种应用。
<!-- XML 配置 --> <bean id="prototypeBean" class="com.example.PrototypeBean" scope="prototype"/> // Java 代码中获取 Bean ApplicationContext context = ...; PrototypeBean bean1 = context.getBean(PrototypeBean.class); PrototypeBean bean2 = context.getBean(PrototypeBean.class); // bean1 和 bean2 是两个不同的实例 System.out.println(bean1 == bean2); // 输出 false设计思想
核心机制:Spring 容器内部维护一个原型 Bean 的模板,每次调用 getBean() 时,基于模板创建一个新对象(通过反射或 CGLIB 动态代理)。优势:避免单例 Bean 的线程安全问题,适用于需要独立状态的场景(如 HTTP 请求处理)。 三、总结 原型模式的优点 高效创建对象 通过复制现有对象来创建新对象,避免了重复的初始化过程,特别适用于创建成本较高的对象(如数据库连接、复杂计算对象)。例如,Spring 的 Prototype Bean 每次请求都会创建一个新实例,避免了单例 Bean 的线程安全问题。 动态配置对象 可以在运行时动态修改克隆对象的属性,而不需要重新初始化。例如,复制一个配置对象后,可以根据需要调整某些参数。 减少子类化 通过复制现有对象来创建新对象,而不是通过继承来扩展功能,避免了类层次结构的复杂性。例如,JavaScript 中的原型继承就是通过复制原型对象来实现的。 标准化对象创建 提供统一的克隆接口(如 Cloneable),使得对象创建过程更加标准化和可控。 原型模式的缺点 深拷贝与浅拷贝问题 默认的 clone() 方法是浅拷贝,如果对象包含引用类型字段,克隆对象和原对象会共享这些字段,可能导致意外的副作用。实现深拷贝需要额外的工作(如手动复制引用类型字段或使用序列化工具)。 实现复杂度 如果对象结构非常复杂(如包含嵌套对象、循环引用等),实现深拷贝可能会变得复杂且容易出错。 破坏封装性 clone() 方法是 Object 类的受保护方法,需要在子类中重写并公开,这可能破坏类的封装性。 性能问题 深拷贝(如基于序列化的拷贝)可能比较耗时,特别是在对象结构复杂或数据量大的情况下。 原型模式的适用场景 对象创建成本高 当对象的创建过程涉及复杂的计算、资源消耗(如数据库连接、网络请求)或耗时操作时,使用原型模式可以显著提高性能。例如,Spring 的 Prototype Bean 适用于需要独立状态的场景。 需要动态配置对象 当对象的配置需要在运行时动态确定时,可以通过克隆现有对象并修改其属性来实现。例如,复制一个配置模板并根据环境调整参数。 避免子类化 当需要通过扩展对象的功能来创建新对象,但又不想引入复杂的类层次结构时,可以使用原型模式。例如,JavaScript 中的原型继承。 需要保持对象状态一致性 当需要创建与现有对象状态相同的新对象时,可以通过克隆来确保状态一致性。例如,游戏中的敌人生成、缓存对象的复制。 框架中的对象管理 在框架中,原型模式常用于管理对象的生命周期和创建过程(如 Spring 的 Prototype Bean、Java 集合框架的 clone() 方法)。【设计模式】【创建型模式】原型模式(Prototype)由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【设计模式】【创建型模式】原型模式(Prototype)”
上一篇
macos设置jdk版本
下一篇
免费搭建个人网站