原型模式大白话讲解
一句话概括
就像复印机,拿个原件一复印,就得到一模一样的新东西
现实生活比喻
场景:做月饼
- 传统方式:每次都要和面、调馅、压模、烘烤(从头开始)
- 原型模式 :拿一个做好的月饼当模子,直接复制出更多一模一样的

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

完整代码示例
基础原型模式
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;
}
适用场景(大白话版)
✅ 适合用原型模式的场景:
-
创建成本高的对象
java// 从数据库加载复杂配置的角色模板 // 复制比重新创建快得多 GameRole template = loadFromDatabase(); // 耗时操作 GameRole newPlayer = template.clone(); // 快速复制 -
避免重复初始化
java// 复杂的初始化过程 Object complexObject = new ComplexObject(); complexObject.initA(); // 复杂初始化 complexObject.initB(); // 复杂初始化 complexObject.initC(); // 复杂初始化 // 直接复制,避免重复初始化 Object newObject = complexObject.clone(); -
运行时动态创建
java// 根据用户选择创建对应对象 String userChoice = getUserInput(); // "warrior" 或 "mage" GameRole role = prototypeManager.getRole(userChoice);
❌ 不适合的场景:
- 对象很简单 (像
new String("hello")这种) - 每个对象都完全不同(没有可复用的模板)
- 复制比创建更复杂(比如要处理复杂的循环引用)
对比其他创建型模式
| 模式 | 比喻 | 特点 |
|---|---|---|
| 工厂模式 | 点餐:告诉厨房要什么,厨房做好给你 | 通过工厂方法创建 |
| 建造者模式 | 定制电脑:一步步选配置,最后组装 | 分步构建复杂对象 |
| 单例模式 | 公司CEO:只有一个,大家共用 | 保证全局唯一实例 |
| 原型模式 | 复印机:拿原件复印,快速得到副本 | 通过复制创建新对象 |
总结
原型模式就是:
- 不想重新造轮子,直接复制现有的
- 避免重复劳动,特别是初始化很复杂的时候
- 快速批量生产,像工厂的模具一样
核心口诀:
创建对象太麻烦,
复制原型更简单。
深拷贝要注意,
引用类型重新建!
就像现实中的:
- 🍪 饼干模具:压一下就是一个新饼干
- 🗝️ 配钥匙:拿原钥匙配新钥匙
- 📷 照片冲印:用底片洗出多张照片
- 🎮 游戏角色:用模板创建新玩家
适用时机:创建比复制更贵的时候!