设计模式>原型模式大白话讲解:就像复印机,拿个原件一复印,就得到一模一样的新东西

原型模式大白话讲解

一句话概括

就像复印机,拿个原件一复印,就得到一模一样的新东西


现实生活比喻

场景:做月饼

  • 传统方式:每次都要和面、调馅、压模、烘烤(从头开始)
  • 原型模式 :拿一个做好的月饼当模子,直接复制出更多一模一样的

场景:配钥匙

  • 传统方式:根据锁的型号重新打造(复杂)
  • 原型模式 :拿原钥匙去配,快速得到新钥匙(简单)

完整代码示例

基础原型模式

java 复制代码
/**
 * 原型模式 - 游戏角色创建示例
 */
public class Main {
    public static void main(String[] args) {
        // 创建原型管理器(就像复印机)
        PrototypeManager manager = new PrototypeManager();
        
        // 客户端使用
        System.out.println("=== 创建游戏角色 ===");
        
        // 通过复制创建新角色,而不是new
        GameRole warrior1 = manager.getRole("warrior");
        warrior1.setName("战士张三");
        warrior1.showInfo();
        
        GameRole warrior2 = manager.getRole("warrior");
        warrior2.setName("战士李四");
        warrior2.showInfo();
        
        GameRole mage1 = manager.getRole("mage");
        mage1.setName("法师王五");
        mage1.showInfo();
        
        GameRole archer1 = manager.getRole("archer");
        archer1.setName("射手赵六");
        archer1.showInfo();
        
        // 验证是不是不同的对象
        System.out.println("\n=== 验证原型模式 ===");
        System.out.println("warrior1 和 warrior2 是同一个对象吗?" + (warrior1 == warrior2));
        System.out.println("但它们有相同的属性和技能模板");
    }
}

/**
 * 抽象原型 - 声明克隆方法
 */
interface Prototype extends Cloneable {
    Prototype clone() throws CloneNotSupportedException;
}

/**
 * 具体原型 - 游戏角色
 */
class GameRole implements Prototype {
    private String name;
    private String type;
    private int level;
    private int hp;
    private int mp;
    private List<String> skills;
    
    // 构造函数 - 创建原型
    public GameRole(String type, int level, int hp, int mp, List<String> skills) {
        this.type = type;
        this.level = level;
        this.hp = hp;
        this.mp = mp;
        this.skills = new ArrayList<>(skills);
        this.name = "原型-" + type;
    }
    
    // 克隆方法 - 核心!
    @Override
    public GameRole clone() throws CloneNotSupportedException {
        GameRole cloned = (GameRole) super.clone();
        // 深拷贝:技能列表也要单独复制
        cloned.skills = new ArrayList<>(this.skills);
        return cloned;
    }
    
    // 设置个性化信息
    public void setName(String name) {
        this.name = name;
    }
    
    public void showInfo() {
        System.out.println("角色: " + name + " [" + type + "]");
        System.out.println("等级: " + level + " | HP: " + hp + " | MP: " + mp);
        System.out.println("技能: " + String.join(", ", skills));
        System.out.println("---");
    }
}

/**
 * 原型管理器 - 管理各种原型
 */
class PrototypeManager {
    private Map<String, GameRole> prototypes = new HashMap<>();
    
    public PrototypeManager() {
        // 初始化各种原型角色
        prototypes.put("warrior", new GameRole("战士", 1, 100, 20, 
            Arrays.asList("重击", "防御", "冲锋")));
            
        prototypes.put("mage", new GameRole("法师", 1, 50, 100, 
            Arrays.asList("火球术", "冰冻术", "治疗术")));
            
        prototypes.put("archer", new GameRole("射手", 1, 70, 50, 
            Arrays.asList("精准射击", "陷阱", "隐身")));
    }
    
    // 获取角色的克隆
    public GameRole getRole(String type) {
        try {
            GameRole prototype = prototypes.get(type);
            if (prototype != null) {
                return prototype.clone(); // 关键:复制而不是直接返回
            }
            return null;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}

运行结果

复制代码
=== 创建游戏角色 ===
角色: 战士张三 [战士]
等级: 1 | HP: 100 | MP: 20
技能: 重击, 防御, 冲锋
---
角色: 战士李四 [战士]
等级: 1 | HP: 100 | MP: 20
技能: 重击, 防御, 冲锋
---
角色: 法师王五 [法师]
等级: 1 | HP: 50 | MP: 100
技能: 火球术, 冰冻术, 治疗术
---
角色: 射手赵六 [射手]
等级: 1 | HP: 70 | MP: 50
技能: 精准射击, 陷阱, 隐身
---

=== 验证原型模式 ===
warrior1 和 warrior2 是同一个对象吗?false
但它们有相同的属性和技能模板

深拷贝 vs 浅拷贝

浅拷贝问题演示

java 复制代码
/**
 * 演示浅拷贝的问题
 */
class ShallowCopyDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        List<String> originalSkills = new ArrayList<>(Arrays.asList("火球", "冰冻"));
        
        GameRole original = new GameRole("法师", 1, 50, 100, originalSkills);
        GameRole shallowCopy = original.clone();
        
        // 修改拷贝对象的技能列表
        shallowCopy.getSkills().add("雷电");
        
        System.out.println("原对象技能: " + original.getSkills());
        System.out.println("拷贝对象技能: " + shallowCopy.getSkills());
        // 结果:两个对象的技能列表都被修改了!
    }
}

解决方案:深拷贝

java 复制代码
// 在clone方法中确保所有引用类型都重新创建
@Override
public GameRole clone() throws CloneNotSupportedException {
    GameRole cloned = (GameRole) super.clone();
    // 深拷贝:创建新的ArrayList,而不是共享同一个
    cloned.skills = new ArrayList<>(this.skills);
    return cloned;
}

适用场景(大白话版)

适合用原型模式的场景:

  1. 创建成本高的对象

    java 复制代码
    // 从数据库加载复杂配置的角色模板
    // 复制比重新创建快得多
    GameRole template = loadFromDatabase(); // 耗时操作
    GameRole newPlayer = template.clone();  // 快速复制
  2. 避免重复初始化

    java 复制代码
    // 复杂的初始化过程
    Object complexObject = new ComplexObject();
    complexObject.initA();  // 复杂初始化
    complexObject.initB();  // 复杂初始化
    complexObject.initC();  // 复杂初始化
    
    // 直接复制,避免重复初始化
    Object newObject = complexObject.clone();
  3. 运行时动态创建

    java 复制代码
    // 根据用户选择创建对应对象
    String userChoice = getUserInput(); // "warrior" 或 "mage"
    GameRole role = prototypeManager.getRole(userChoice);

不适合的场景:

  1. 对象很简单 (像new String("hello")这种)
  2. 每个对象都完全不同(没有可复用的模板)
  3. 复制比创建更复杂(比如要处理复杂的循环引用)

对比其他创建型模式

模式 比喻 特点
工厂模式 点餐:告诉厨房要什么,厨房做好给你 通过工厂方法创建
建造者模式 定制电脑:一步步选配置,最后组装 分步构建复杂对象
单例模式 公司CEO:只有一个,大家共用 保证全局唯一实例
原型模式 复印机:拿原件复印,快速得到副本 通过复制创建新对象

总结

原型模式就是:

  • 不想重新造轮子,直接复制现有的
  • 避免重复劳动,特别是初始化很复杂的时候
  • 快速批量生产,像工厂的模具一样

核心口诀:

创建对象太麻烦,

复制原型更简单。

深拷贝要注意,

引用类型重新建!

就像现实中的:

  • 🍪 饼干模具:压一下就是一个新饼干
  • 🗝️ 配钥匙:拿原钥匙配新钥匙
  • 📷 照片冲印:用底片洗出多张照片
  • 🎮 游戏角色:用模板创建新玩家

适用时机:创建比复制更贵的时候!

相关推荐
披着羊皮不是狼3 小时前
HTTP 与 API 入门:理解前后端交互原理
java·网络协议·http·交互
2401_841495643 小时前
【操作系统】模拟真实操作系统核心功能的Java实现
java·操作系统·进程管理·系统调用·并发控制·中断处理·cpu调度
南方的狮子先生3 小时前
【数据结构】从线性表到排序算法详解
开发语言·数据结构·c++·算法·排序算法·1024程序员节
程序员皮皮林3 小时前
Java 25 正式发布:更简洁、更高效、更现代!
java·开发语言·python
好家伙VCC4 小时前
**发散创新:AI绘画编程探索与实践**随着人工智能技术的飞速发展,AI绘
java·人工智能·python·ai作画
勇者无畏4044 小时前
基于 Spring AI Alibaba 搭建 Text-To-SQL 智能系统(前置介绍)
java·后端·spring·prompt·embedding
练习时长一年4 小时前
IDEA开发常用快捷键总结
java·ide·intellij-idea
温柔53294 小时前
仓颉语言异常捕获机制深度解析
java·服务器·前端
运维李哥不背锅4 小时前
Ansible 的变量与模板:实现更灵活的自动化配置
java·自动化·ansible