一.原型模式的定义
原型模式是一种创建型设计模式,通过复制现有对象(原型)生成新对象,避免重复初始化成本。需了解以下关键概念:
- 浅拷贝:复制基本类型字段,引用类型字段共享内存地址(修改新对象会影响原对象)。
- 深拷贝:递归复制引用对象(如通过序列化/手动复制),新旧对象完全独立。
二.实现方式
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");
}
@Override
public 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中设计模式干货,第一时间推送给你!
🔔 有什么问题也可以在评论区讨论🤝🤝🤝