原型模式通過拷貝現有對象創建新對象,避免昂貴的構造過程。Java Cloneable 接口提供語言級支援,但深淺拷貝細節決定成敗。
class Student implements Cloneable {
String name; // 不可變,拷貝安全
List friends; // 可變,淺拷貝共享!
@Override protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 默認淺拷貝
}
}
// 測試
Student s1 = new Student(); s1.friends = new ArrayList<>(Arrays.asList("紅","梅"));
Student s2 = (Student) s1.clone();
s2.friends.add("剛"); // 修改 s2 的列表
System.out.println(s1.friends); // [紅, 梅, 剛] ← s1 也被修改了!
System.out.println(s2.friends); // [紅, 梅, 剛]
結論:clone() 默認實現淺拷貝,可變引用類型字段共享底層對象。
原理:對象 → 字節流 (持久化) → 新對象,完全獨立內存。
public Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this); // 要求實現 Serializable
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject(); // 返回全新獨立對象圖
}
前提:對象及所有引用字段必須實現 Serializable,transient 字段不會被拷貝。
| 拷貝方式 | 性能 | 適用場景 | 注意事項 |
|---|---|---|---|
| 賦值引用 | 極快 | 只讀共享、飛量模式 | 修改互影響 |
| 淺拷貝 clone() | 快 | 字段全為基本類型/不可變對象 | 可變字段共享風險 |
| 深拷貝序列化 | 較慢 | 複雜對象圖、含可變引用字段 | 需 Serializable、transient 處理 |
| 深拷貝手動 new | 中等 | 高性能要求、精確控制拷貝邏輯 | 代碼冗長、維護成本高 |
copy constructor 或 static factory copy 替代 clone() (Effective Java 項目 13)clone() 時:實現 Cloneable、覆寫 public clone()、決定深淺策略並文檔化Apache Commons Lang SerializationUtils.clone()原型模式核心價值:以拷貝代替創建,隱藏具體構造細節,支援運行時動態配置對象類型。