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

【HeadFirst系列之HeadFirstJava】第18天之深入理解原型模式:从问题到解决方案(含 Java 代码示例)

深入理解原型模式:从问题到解决方案(含 Java 代码示例)

在软件开发中,我们经常需要创建对象,而有些对象的创建成本较高或者结构较为复杂。如何在不破坏封装的前提下,高效地创建对象? 这正是**原型模式(Prototype Pattern)**要解决的问题。

本篇文章将基于《Head First 设计模式》的内容,深入剖析原型模式的概念、应用场景、优缺点,并结合 JDK 和 Spring 框架的实际应用,提供详细的 Java 代码示例,帮助你掌握这一设计模式的精髓。


📌 1. 什么是原型模式?

原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制(克隆)已有对象来创建新的对象,而不是通过 new 关键字实例化对象。

它的核心思想是原型对象提供一个克隆方法,让客户端在需要创建对象时,直接调用该方法来获取副本

定义用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。


📌 2. 传统对象创建的问题

在实际开发中,我们通常通过 new 关键字创建对象:

Person person1 = new Person("Alice", 25);

但当对象的初始化成本较高时(如涉及数据库查询、复杂计算等),反复 new 一个新对象会影响性能。

比如,一个数据库查询返回的用户对象,如果需要多次创建相同的用户对象,每次都去查询数据库,会造成资源浪费。

原型模式就是为了解决高成本对象的重复创建问题


📌 3. 原型模式如何解决问题?

原型模式提供了一种对象克隆机制,让我们可以基于一个已有对象创建新对象,而不必重新执行复杂的初始化逻辑

实现方式:

  • Java 提供 Cloneable 接口,允许对象通过 clone() 方法复制自身。
  • 通过**浅拷贝(shallow copy)或深拷贝(deep copy)**实现克隆。

📌 4. Java 原型模式代码示例

我们用一个 “用户信息” 示例来演示原型模式。

🎯 1️⃣ 定义一个可克隆的类

class User implements Cloneable {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // 浅拷贝
    }

    public void showUser() {
        System.out.println("User: " + name + ", Age: " + age);
    }
}

clone() 方法调用 super.clone(),表示让 JVM 直接拷贝该对象。

🎯 2️⃣ 进行对象克隆

public class PrototypeDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        User user1 = new User("Alice", 25);
        User user2 = (User) user1.clone();  // 克隆 user1

        user1.showUser();
        user2.showUser();

        System.out.println("user1 == user2 ? " + (user1 == user2)); // false,表明是两个不同对象
    }
}

运行结果:

User: Alice, Age: 25
User: Alice, Age: 25
user1 == user2 ? false

✅ 说明: 克隆后的 user2user1 是两个不同的对象,但数据相同。


📌 5. 原型模式的应用场景

✅ 适用于:

  1. 创建对象成本较高的场景(如数据库查询、网络请求等)。
  2. 对象结构复杂,且需要避免 new 关键字重复创建
  3. 系统需要提供多个类似对象,而彼此之间仅有少量差异

🚫 不适用于:

  1. 类中包含复杂对象引用,且不支持深拷贝时(浅拷贝可能导致共享引用问题)。
  2. 对象的克隆逻辑过于复杂,甚至比直接 new 还要耗费性能

📌 6. 深拷贝 vs 浅拷贝

浅拷贝(Shallow Copy):仅复制对象的基本属性,对于对象引用类型,仅复制内存地址(原对象和克隆对象共享同一个引用对象)。
深拷贝(Deep Copy):不仅复制基本属性,还创建新的对象实例,保证克隆后的对象互不影响。

🎯 深拷贝代码实现

class Address implements Cloneable {
    private String city;
    public Address(String city) { this.city = city; }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Person implements Cloneable {
    private String name;
    private Address address;

    public Person(String name, String city) {
        this.name = name;
        this.address = new Address(city);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        cloned.address = (Address) address.clone(); // 深拷贝
        return cloned;
    }
}

深拷贝的关键是对引用对象也执行 clone() 方法,确保复制的是一个新的实例,而不是共享同一个对象。


📌 7. JDK 和 Spring 中的应用

🎯 JDK 应用

  1. Object.clone():Java 语言中的 clone() 方法就是原型模式的体现。
  2. ArrayList.clone()ArrayList 实现了 Cloneable 接口,可通过 clone() 方法创建副本。

🎯 Spring 框架中的应用

  1. Spring Bean 的原型模式(Prototype Scope)
    @Bean
    @Scope("prototype")
    public User user() {
        return new User("Alice", 25);
    }
    
    Spring 提供的 prototype 作用域,每次获取 Bean 都会返回一个新实例,这与原型模式的思想一致。

📌 8. 原型模式的优缺点

✅ 优点

  1. 提高对象创建效率,避免重复初始化高成本对象。
  2. 封装克隆过程,客户端无需关注对象创建细节。
  3. 简化对象创建逻辑,减少 new 关键字的使用。

🚫 缺点

  1. 对象的拷贝可能涉及复杂的深拷贝逻辑,容易出错。
  2. 必须确保所有引用对象都支持克隆,否则容易出现共享引用问题。
  3. Java 的 Cloneable 接口设计较为陈旧,官方推荐使用 序列化 或者 手动拷贝构造函数 来代替 clone() 方法。

📌 9. 总结

  • 原型模式 通过克隆对象代替 new 关键字,适用于高成本对象的创建
  • Java 提供 Cloneable 接口支持浅拷贝,深拷贝需要手动实现。
  • JDK 和 Spring 中都使用了原型模式,例如 clone() 方法、Spring 的 Prototype Scope。

💡 原型模式的核心: “用复制代替创建,提升对象创建效率!” 🚀


http://www.kler.cn/a/583830.html

相关文章:

  • Spring 事务失效的 8 种场景!
  • HOT100——链表篇Leetcode160. 相交链表
  • Tool和Agent
  • 如何重置 MySQL root 用户的登录密码?
  • 项目型公司如何规避项目风险
  • Mysql表的查询
  • python如何非阻塞的监听按键(win linux亲测)
  • 【存储中间件】Redis核心技术与实战(一):Redis入门与应用(常用数据结构:集合set、有序集合ZSET)
  • 【从零开始学习计算机科学】数据库系统(八)数据库的备份和恢复
  • 制造执行系统(MES)系统基本流程
  • 22 - 天 TCPIP 四层模型是什么?Cookie、Session、Token 之间有什么区别?从网络角度来看,用户从输入网址到网页显示,期间发生了什么?
  • 大白话在 React 中,如何处理表单的复杂验证逻辑?
  • Java中的Logback:高效日志管理解析
  • 如何设计微服务及其设计原则?
  • 【21】单片机编程核心技巧:if语句逻辑与真假判断
  • MCP服务协议详细介绍
  • 【春招笔试】2025.03.13-携程春招笔试
  • CCF CSP 第30次(2023.09)(1_坐标变换_C++)(先输入再计算;边输入边计算)
  • Docker配置代理,以保证可以快速拉取镜像
  • 基于ESP32的桌面小屏幕实战[8]:任务创建