原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制一个已有的对象(即"原型")来创建新对象,而不是通过构造函数或工厂方法。这种方式可以避免重复的初始化过程,尤其在对象创建代价较大时非常有用。
一、基本概念
🎯 目的
通过克隆已有对象来创建新对象,以提高性能和简化对象创建逻辑。
🧩 主要角色
角色 | 描述 |
---|---|
Prototype (原型接口) |
定义克隆自身的接口,通常是 clone() 方法 |
ConcretePrototype (具体原型类) |
实现 clone() 方法的具体类 |
Client(客户端) | 使用原型对象来创建新的对象副本 |
二、Java 中的实现方式
1. 实现 Cloneable
接口并重写 clone()
java
public class Product implements Cloneable {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
protected Product clone() {
try {
return (Product) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // 不会发生
}
}
// Getter 和 Setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
@Override
public String toString() {
return "Product{name='" + name + "', price=" + price + "}";
}
}
2. 测试使用
java
public class Client {
public static void main(String[] args) {
Product product1 = new Product("Laptop", 999.99);
Product product2 = product1.clone();
System.out.println("Original: " + product1);
System.out.println("Cloned: " + product2);
product1.setName("Updated Laptop");
product1.setPrice(1099.99);
System.out.println("\nAfter change original:");
System.out.println("Original: " + product1);
System.out.println("Cloned: " + product2);
}
}
三、浅拷贝 vs 深拷贝
类型 | 是否复制引用字段 | 实现方式 | 应用场景 |
---|---|---|---|
浅拷贝(Shallow Copy) | 否(只复制引用地址) | 默认 super.clone() |
对象不含引用字段或无需隔离引用 |
深拷贝(Deep Copy) | 是(递归复制引用对象) | 手动对每个引用字段调用 clone() 或序列化 |
对象含有嵌套对象,需要完全独立 |
✅ 示例:深拷贝实现
java
class Category implements Cloneable {
private String categoryName;
public Category(String categoryName) {
this.categoryName = categoryName;
}
@Override
protected Category clone() {
try {
return (Category) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
public String getCategoryName() { return categoryName; }
public void setCategoryName(String categoryName) { this.categoryName = categoryName; }
@Override
public String toString() {
return "Category{" + "categoryName='" + categoryName + "'}";
}
}
class Product implements Cloneable {
private String name;
private double price;
private Category category;
public Product(String name, double price, Category category) {
this.name = name;
this.price = price;
this.category = category;
}
@Override
protected Product clone() {
try {
Product product = (Product) super.clone();
if (this.category != null) {
product.category = this.category.clone(); // 手动深拷贝
}
return product;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
// Getter 和 Setter...
}
四、优点
- 性能优化:避免复杂的构造逻辑,尤其是创建对象代价较高时。
- 简化对象创建 :不需要知道对象是如何构建的,只需调用
clone()
。 - 动态配置:可以在运行时根据已有对象生成新对象,并进行微调。
五、适用场景
- 创建对象的代价很大(如频繁访问数据库、远程资源加载等)。
- 对象之间状态差异小,适合基于已有对象进行微调。
- 需要动态配置对象结构而不破坏封装性。
六、注意事项
- 必须实现
Cloneable
接口,否则会抛出异常。 - 注意区分浅拷贝与深拷贝,避免因引用共享导致的数据污染。
- 如果类中有 final 字段,可能需要特殊处理(因为不能在克隆后重新赋值)。
如果你有具体的业务需求或想看更复杂的原型模式示例(比如结合 JSON 序列化实现深拷贝),我可以为你提供完整代码示例。