一.原型模式的定義
????????原型模式是一種創建型設計模式,通過復制現有對象(原型)生成新對象,避免重復初始化成本。需了解以下關鍵概念:
- ?淺拷貝?:復制基本類型字段,引用類型字段共享內存地址(修改新對象會影響原對象)。
- ?深拷貝?:遞歸復制引用對象(如通過序列化/手動復制),新舊對象完全獨立。
二.實現方式
2.1.?Java 原生實現(了解)
實現Cloneable接口,聲明對象可以被克隆。Cloneable接口是個空接口,有僅有標志作用
通過Object的clone()方法復制現有對象生成新實例,而非通過構造函數創建,默認是淺拷貝。
也可以深拷貝,但是需要手動賦值,且需處理異常,本章不演示。
2.1.1.案例
/*** 使用 Cloneable 接口實現淺拷貝* 注意:只復制了對象本身,未復制內部的 List 字段** 該類演示了 Java 原生 Cloneable 接口的使用方式。* clone() 方法調用 super.clone(),僅復制對象自身,不復制引用字段(如 List)* 因此,克隆后的對象與原對象共享同一個 List 實例,修改其中一個會影響另一個。* 適用于對象結構簡單、無需深拷貝的場景。** @author demo*/
public class ShallowCloneWithCloneable implements Cloneable {private String name;private List<String> tags = new ArrayList<>();public ShallowCloneWithCloneable(String name) {//注意:String是不可變的,所以淺克隆和深克隆效果一致this.name = name;//賦默認值,方便查看是否被可弄this.tags.add("default");}@Overridepublic ShallowCloneWithCloneable clone() {try {return (ShallowCloneWithCloneable) super.clone();} catch (CloneNotSupportedException e) {throw new RuntimeException(e);}}public void addTag(String tag) {tags.add(tag);}public void display() {System.out.println("Name: " + name);System.out.println("Tags: " + tags);}
}public static void main(String[] args) {// 創建原始對象ShallowCloneWithCloneable original = new ShallowCloneWithCloneable("Original Object");System.out.println("原始對象:");original.display();// 克隆對象ShallowCloneWithCloneable copy = original.clone();System.out.println("克隆對象:");copy.display();// 修改克隆對象的引用字段System.out.println("修改克隆對象的 tags...");copy.addTag("new-tag");// 查看原始對象是否受影響System.out.println("原始對象現在的狀態:");original.display();System.out.println("克隆對象現在的狀態:");copy.display();}
?2.2.2.運行結果
原始對象:
Name: Original Object
Tags: [default]
克隆對象:
Name: Original Object
Tags: [default]
修改克隆對象的 tags...
原始對象現在的狀態:
Name: Original Object
Tags: [default, new-tag]
克隆對象現在的狀態:
Name: Original Object
Tags: [default, new-tag]
2.2.序列化與反序列化機制實現
2.2.1.案例
/*** 使用序列化與反序列化機制實現深拷貝* 注意:所有字段都會被重新創建,包括引用類型字段** 該類演示了如何通過 Java 的序列化和反序列化機制實現真正的深拷貝。* 對象及其所有引用字段都會被完全復制,確保克隆后的對象與原對象完全獨立。* 適用于復雜對象的深拷貝,無需手動復制字段。* 要求類必須實現 Serializable 接口。** @author demo*/
public class SerializableDeepClone implements Serializable {private String name;private List<String> tags = new ArrayList<>();public SerializableDeepClone(String name) {this.name = name;this.tags.add("default");}/*** 深拷貝方法* @return 一個新的、獨立的對象副本*/public SerializableDeepClone clone() {try {// 序列化ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);// 反序列化ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (SerializableDeepClone) ois.readObject();} catch (Exception e) {throw new RuntimeException("深拷貝失敗", e);}}public void addTag(String tag) {tags.add(tag);}public void display() {System.out.println("Name: " + name);System.out.println("Tags: " + tags);}
}public static void main(String[] args) {// 創建原始對象SerializableDeepClone original = new SerializableDeepClone("Original Object");System.out.println("原始對象:");original.display();// 克隆對象SerializableDeepClone copy = original.clone();System.out.println("\n克隆對象:");copy.display();// 修改克隆對象的引用字段System.out.println("\n修改克隆對象的 tags...");copy.addTag("new-tag");// 查看原始對象是否受影響System.out.println("\n原始對象現在的狀態:");original.display();System.out.println("\n克隆對象現在的狀態:");copy.display();}
2.2.2.運行結果
原始對象:
Name: Original Object
Tags: [default]克隆對象:
Name: Original Object
Tags: [default]修改克隆對象的 tags...
原始對象現在的狀態:
Name: Original Object
Tags: [default]克隆對象現在的狀態:
Name: Original Object
Tags: [default, new-tag]
2.3.?SerializationUtils實現
2.3.1.案例
<!--引入依賴-->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version>
</dependency>
/*** 使用 Apache Commons 的 SerializationUtils.clone() 實現深拷貝* 注意:所有字段都會被重新創建,包括引用類型字段** 該類演示了如何通過 Apache Commons Lang 提供的 SerializationUtils.clone() 方法實現真正的深拷貝。* 對象及其所有引用字段都會被完全復制,確保克隆后的對象與原對象完全獨立。* 適用于復雜對象的深拷貝,簡化開發并避免手動復制字段。* 要求類必須實現 Serializable 接口。** @author demo*/
public class SerializableWithUtilsClone implements Serializable {private String name;private List<String> tags = new ArrayList<>();public SerializableWithUtilsClone(String name) {this.name = name;this.tags.add("default");}/*** 深拷貝方法,使用 Apache Commons Lang 的 SerializationUtils.clone()* @return 一個新的、獨立的對象副本*/public SerializableWithUtilsClone deepCopy() {return SerializationUtils.clone(this);}public void addTag(String tag) {tags.add(tag);}public void display() {System.out.println("Name: " + name);System.out.println("Tags: " + tags);}
}public static void main(String[] args) {// 創建原始對象SerializableWithUtilsClone original = new SerializableWithUtilsClone("Original Object");System.out.println("原始對象:");original.display();// 克隆對象SerializableWithUtilsClone copy = original.deepCopy();System.out.println("克隆對象:");copy.display();// 修改克隆對象的引用字段System.out.println("修改克隆對象的 tags...");copy.addTag("new-tag");// 查看原始對象是否受影響System.out.println("原始對象現在的狀態:");original.display();System.out.println("克隆對象現在的狀態:");copy.display();}
2.3.2.運行結果
原始對象:
Name: Original Object
Tags: [default]
克隆對象:
Name: Original Object
Tags: [default]
修改克隆對象的 tags...
原始對象現在的狀態:
Name: Original Object
Tags: [default]
克隆對象現在的狀態:
Name: Original Object
Tags: [default, new-tag]
💡 如果本文對你有幫助,點擊右上角【訂閱專欄】或左上角關注我 ?
🔔 完整的23中設計模式干貨,第一時間推送給你!
🔔 有什么問題也可以在評論區討論🤝🤝🤝?