原型模式
Prototype — 通过复制已有对象来创建新对象,而不是通过 new
一句话理解
用一个已有对象作为模板,通过克隆(复制)它来创建新对象。
解决什么问题
- 创建对象的成本很高(比如需要查数据库、做大量计算)
- 需要创建大量相似对象,只有少数属性不同
- 想避免复杂的构造逻辑
怎么写
Java 中通过实现 Cloneable 接口:
public class Resume implements Cloneable {
private String name;
private String position;
private String company;
public Resume(String name) {
this.name = name;
}
public void setPosition(String position) { this.position = position; }
public void setCompany(String company) { this.company = company; }
// 克隆方法
@Override
public Resume clone() {
try {
return (Resume) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return name + " - " + position + " @ " + company;
}
}// 使用:基于原型克隆,再修改差异部分
Resume base = new Resume("张三");
base.setPosition("Java 开发");
base.setCompany("公司A");
Resume r2 = base.clone();
r2.setCompany("公司B"); // 只改投递公司
Resume r3 = base.clone();
r3.setCompany("公司C");
System.out.println(base); // 张三 - Java 开发 @ 公司A
System.out.println(r2); // 张三 - Java 开发 @ 公司B
System.out.println(r3); // 张三 - Java 开发 @ 公司C浅拷贝 vs 深拷贝
- 浅拷贝:只复制基本类型字段,引用类型字段仍然指向同一个对象(
super.clone()默认行为) - 深拷贝:引用类型也递归复制,完全独立
// 深拷贝需要手动处理引用类型
@Override
public Resume clone() {
Resume copy = (Resume) super.clone();
copy.skills = new ArrayList<>(this.skills); // 引用类型手动复制
return copy;
}前端中的原型模式
JavaScript 的原型链本身就是原型模式的体现:
// Object.create 就是原型模式
const base = { type: 'animal', speak() { console.log('...') } }
const dog = Object.create(base)
dog.speak() // 通过原型链调用
// 日常中更常用展开运算符做浅拷贝
const config = { ...defaultConfig, timeout: 3000 }使用场景
Object.create()、展开运算符{ ...obj }- Java
clone()方法 - 需要批量创建相似对象的场景
- Spring 中
@Scope("prototype")每次获取 Bean 都创建新实例