JAVA重点基础、进阶知识及易错点总结(32)设计模式(建造者、原型)

🚀 Java 巩固进阶 · 第 32 天

主题:设计模式(建造者、原型)------ 复杂对象创建方案

📅 进度概览 :继昨天的单例/工厂模式之后,今天学习 另外两种创建型设计模式。建造者模式解决"复杂对象构建",原型模式解决"对象克隆复制",两者在实际开发中应用广泛。

💡 核心价值

  • 构建优雅:建造者模式用链式调用替代"伸缩构造器",代码可读性提升 10 倍。
  • 克隆高效:原型模式避免重复初始化,适合"模板复制"场景(如简历克隆、订单复制)。
  • 框架关联:理解 StringBuilder、AlertDialog、Spring Bean 克隆的底层思想。
  • 面试加分:深浅克隆区别、Builder 模式适用场景是高级开发常考题。

一、建造者模式(Builder):链式构建复杂对象 🔨

1. 为什么需要建造者模式?

java 复制代码
// ❌ 问题:伸缩构造器反模式(参数多、易出错、可读性差)
public class Computer {
    // 10 个参数,调用时根本不知道每个参数含义!
    public Computer(String cpu, String ram, String disk, String gpu, 
                   String motherboard, String power, String case_, 
                   String cooling, String monitor, String keyboard) { ... }
}
// 调用:
new Computer("i7", "16G", "512G", "RTX3060", null, null, "ATX", null, null, null);
// 😵 哪个是 null?参数顺序记错怎么办?

// ✅ 解决:建造者模式,链式调用,语义清晰
Computer computer = new Computer.Builder()
    .cpu("i7")
    .ram("16G")
    .disk("512G")
    .gpu("RTX3060")
    .case_("ATX")
    .build();  // 最后一步构建,中间参数顺序随意,未设置用默认值

2. 标准实现模板(⭐ 背下来!)

java 复制代码
public class Computer {
    // 1. 私有字段
    private final String cpu;
    private final String ram;
    private final String disk;
    private final String gpu;
    // ... 其他字段
    
    // 2. 私有构造器,只允许 Builder 访问
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        // ... 赋值
    }
    
    // 3. 静态内部类 Builder
    public static class Builder {
        // 与外部类相同的字段
        private String cpu = "i3";      // 默认值
        private String ram = "8G";
        private String disk = "256G";
        private String gpu = "集成显卡";
        
        // 链式设置方法(返回 this)
        public Builder cpu(String cpu) { this.cpu = cpu; return this; }
        public Builder ram(String ram) { this.ram = ram; return this; }
        public Builder disk(String disk) { this.disk = disk; return this; }
        public Builder gpu(String gpu) { this.gpu = gpu; return this; }
        
        // 构建方法(校验 + 创建)
        public Computer build() {
            // 可选:参数校验
            if (cpu == null) throw new IllegalArgumentException("CPU 不能为空");
            return new Computer(this);
        }
    }
    
    // getter 方法(省略)
}

3. 🔍 关键细节解析

设计点 原因 注意事项
静态内部类 避免外部类膨胀,隔离构建逻辑 Builder 可访问外部类私有字段
字段 final 保证对象不可变,线程安全 构建完成后不能修改
链式返回 this 支持流畅调用 每个 setter 必须 return this
build() 校验 确保对象状态合法 在构建最后一步集中校验

💡 生产实践

  • Lombok 的 @Builder 注解可自动生成 Builder 代码
  • 但建议手动写一次,理解原理后再用注解

二、原型模式(Prototype):克隆对象的高效方案 📋

1. 为什么需要原型模式?

复制代码
🎯 场景:创建对象成本高(如:查数据库初始化、复杂计算)
❌ 问题:每次 new 都要重复初始化,浪费资源
✅ 解决:克隆已有对象(原型),快速复制 + 局部修改

2. Cloneable 接口与 clone() 方法

java 复制代码
// ✅ 标准实现:实现 Cloneable + 重写 clone()
public class Resume implements Cloneable {
    private String name;
    private String experience;  // 工作经历(可变对象)
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();  // 浅克隆:调用 Object.clone()
    }
}

// 使用
Resume r1 = new Resume();
r1.setName("Alice");
Resume r2 = (Resume) r1.clone();  // 快速复制

3. ⚠️ 浅克隆 vs 深克隆(⭐ 面试高频)

java 复制代码
// 🐛 浅克隆问题:只克隆对象本身,内部引用对象共享
Resume r1 = new Resume();
r1.setExperience(new Experience("2020-2024", "Java 开发"));
Resume r2 = (Resume) r1.clone();

r2.getExperience().setCompany("New Corp");  // 修改 r2 的经历
System.out.println(r1.getExperience().getCompany());  // ❌ r1 也被改了!

// ✅ 深克隆方案 1:手动克隆引用字段
@Override
protected Object clone() throws CloneNotSupportedException {
    Resume cloned = (Resume) super.clone();
    // 手动克隆可变字段
    cloned.experience = (Experience) this.experience.clone();
    return cloned;
}

// ✅ 深克隆方案 2:序列化(通用但性能略低)
public Resume deepClone() {
    // 1. 序列化到字节数组
    // 2. 反序列化为新对象
    // 所有引用字段自动克隆,无需手动处理
}

4. 🔍 深浅克隆对比表

特性 浅克隆 深克隆
实现方式 super.clone() 手动克隆 / 序列化
引用字段 共享同一对象 克隆新对象
性能 ⚡ 快(内存拷贝) 🐢 略慢(递归/序列化)
适用场景 对象无引用字段 / 引用不可变 对象含可变引用字段
代码复杂度 ✅ 简单 ⚠️ 需处理每个引用字段

💡 记忆口诀

"浅克隆只拷贝外壳,深克隆连内脏一起复制"


三、🎯 今日实战任务:模式综合应用

任务 1:用建造者模式创建"电脑配置"

java 复制代码
/**
 * 要求:
 * 1. 定义 Computer 类,包含 8 个字段(cpu/ram/disk/gpu/主板/电源/机箱/散热)
 * 2. 实现 Builder 内部类,支持链式调用
 * 3. 设置默认值,build() 时校验关键字段(如 cpu 不能为空)
 * 4. 测试:用不同参数构建 3 台电脑,打印配置
 * 
 * 💡 挑战:
 * - 添加"构建报告"功能:build() 时输出配置摘要
 * - 思考:如果字段增加到 20 个,Builder 模式的优势是否更明显?
 */

任务 2:用原型模式实现"简历克隆"

java 复制代码
/**
 * 业务场景:求职者投递不同公司,简历内容相似但公司名/职位不同
 * 
 * 要求:
 * 1. 定义 Resume 类(姓名/经历列表),实现 Cloneable
 * 2. 实现浅克隆,测试修改克隆对象的经历是否影响原对象
 * 3. 实现深克隆(手动克隆经历列表),验证隔离性
 * 4. 对比:new 新简历 vs 克隆简历的耗时(模拟经历初始化耗时)
 * 
 * 💡 提示:
 * - 经历列表用 ArrayList,注意集合的克隆
 * - 深克隆可用序列化:ObjectOutputStream / ObjectInputStream
 */

任务 3:建造者 + 原型组合实战

java 复制代码
/**
 * 业务场景:订单系统 - 复制历史订单生成新订单
 * 
 * 要求:
 * 1. 用建造者模式创建 Order 对象(商品列表/收货地址/支付方式)
 * 2. 为 Order 实现 clone() 方法(深克隆商品列表)
 * 3. 场景:用户"再来一单",克隆旧订单 → 修改收货地址 → 提交
 * 4. 验证:新旧订单的商品列表是否独立(修改一个不影响另一个)
 * 
 * 💡 思考:
 * - 为什么订单克隆要用深克隆?(商品可能后续修改价格/库存)
 * - 如果商品对象本身很大,克隆是否划算?(空间换时间)
 */

任务 4:对比实验:Builder vs 传统构造器

java 复制代码
/**
 * 要求:
 * 1. 用传统构造器 + 用 Builder 分别创建同一个复杂对象
 * 2. 统计代码行数、可读性、维护成本
 * 3. 模拟"新增一个可选字段",对比两种方案的修改范围
 * 
 * 💡 预期结论:
 * - Builder 代码略多,但调用方代码极简
 * - 新增字段时,Builder 只需加一个 setter,调用方无需修改
 * - 符合开闭原则:对扩展开放,对修改关闭
 */

📝 第 32 天 · 核心总结(极简背诵版)

  1. 建造者模式核心

    java 复制代码
    // 静态内部类 + 链式 setter + build() 构建
    new Builder().cpu("i7").ram("16G").build();
    // ✅ 适用:参数多、有默认值、需校验的复杂对象
  2. 原型模式核心

    java 复制代码
    // 实现 Cloneable + 重写 clone()
    Object clone = obj.clone();
    // ⚠️ 默认浅克隆,引用字段需手动深克隆
  3. 深浅克隆区别

    复制代码
    浅克隆:只拷贝对象本身,引用字段共享
    深克隆:递归拷贝所有引用字段,完全独立
    选择:可变引用用深克隆,不可变/无引用用浅克隆
  4. 生产建议

    • ✅ 复杂对象构建优先 Builder 模式(或 Lombok @Builder)
    • ✅ 模板复制场景用原型模式(如配置克隆、订单复制)
    • ❌ 避免滥用 clone(),优先用构造器 + 工厂(更清晰)

明天预告 :🎭 设计模式(代理、装饰器) ------ 增强对象功能的两种套路!

  • 静态代理 vs 动态代理(JDK/CGLIB)
  • 装饰器模式:动态增强对象功能(如 IO 缓冲流)
  • 代理与装饰器的区别(意图不同)
  • 实战:用动态代理为 Service 添加日志/事务功能

准备好了吗?明天我们学习"对象增强"的两种经典方案! ✨🔧

相关推荐
qq_372154235 分钟前
CSS如何改变单个网格项目的对齐方式
jvm·数据库·python
kexnjdcncnxjs6 分钟前
CodeIgniter4安全加固指南:防御XSS与CSRF攻击
jvm·数据库·python
2401_871492856 分钟前
Imagick PDF 处理失败的常见原因与解决方案
jvm·数据库·python
littleM8 分钟前
深度拆解 HermesAgent(六):研究功能与测试体系
开发语言·人工智能·python·架构·ai编程
geovindu10 分钟前
go: Observer Pattern
开发语言·观察者模式·设计模式·golang
CHANG_THE_WORLD11 分钟前
使用python调用podofogc文件 批量处理 pdf文件
windows·python·pdf
隔壁大炮11 分钟前
CNN图像分类案例
人工智能·pytorch·python·深度学习·算法·分类·cnn
深邃-16 分钟前
【Web安全】-Kali,Linux配置(2):Java环境配置,Python环境配置,Conda使用,PIP配置使用,SSH远程登录
java·linux·python·安全·web安全·网络安全·php
jjjava2.016 分钟前
Java多线程编程:从入门到实战
java·开发语言
Seven9717 分钟前
Tomcat 线程池的设计与实现:StandardThreadExecutor
java