原型模式
原型模式是一种创建型设计模式 (Creational Pattern),它允许您通过复制现有对象来创建新对象,而无需使代码依赖于这些对象的具体类。
特点
- 高效创建:避免重复执行代价高昂的初始化过程(如数据库查询、文件I/O、复杂计算)。
- 简化对象创建:客户端无需了解对象创建的复杂细节,只需调用克隆方法。
- 动态性:可以在运行时动态地添加或移除可被“实例化”的对象类型。
- 独立于具体类:客户端代码与具体原型类解耦,只需依赖原型接口。
- 拷贝控制:开发者可以精确控制是进行浅拷贝(Shallow Copy)还是深拷贝(Deep Copy)。
核心组成
- 原型接口 (Prototype Interface):
- 声明一个用于克隆自身的操作(通常是
clone()
方法)。 - 在Java中,通常通过实现
Cloneable
接口(标记接口)并重写Object.clone()
方法来实现。
- 声明一个用于克隆自身的操作(通常是
- 具体原型 (Concrete Prototype):
- 实现原型接口的具体类。
- 提供
clone()
方法的具体实现,定义如何复制自身(浅拷贝或深拷贝)。
- 客户端 (Client):
- 持有对一个或多个原型对象的引用。
- 通过调用原型对象的
clone()
方法来创建新的对象实例,而不是使用new
关键字。
**核心思想 **
“复制”优于“构造”。与其每次都从头开始(通过构造函数)创建一个新对象,不如复制一个已经配置好、初始化完成的“原型”对象。这就像复印一份已填写好的表格,比重新手写一份要快得多。
使用场景
场景描述 | 说明 |
---|---|
对象创建开销巨大 | 当通过构造函数创建对象需要进行耗时的数据库操作、网络请求、复杂计算或大量I/O时,克隆一个已存在的实例可以显著提升性能。 |
运行时动态确定对象类型 | 当需要在程序运行时才决定创建哪种类型的对象,且这些类型在编译时无法预知。原型模式允许在运行时注册和克隆任意原型。 |
避免复杂的继承层次初始化 | 当对象的初始化过程非常复杂,涉及多个继承层次的构造函数调用时,直接克隆一个已正确初始化的实例更为简单。 |
创建对象的多个相似副本 | 当需要创建大量具有相同基础配置但可能有微小差异的对象时(如游戏中的NPC、UI组件、配置模板),原型模式非常高效。 |
希望隐藏对象创建的复杂性 | 客户端代码不关心对象是如何一步步创建和初始化的,只关心最终能得到一个可用的副本。 |
示例
java
public interface DocumentPrototype extends Cloneable {
DocumentPrototype cloneDocument() throws CloneNotSupportedException;
}
java
@ToString
@Data
public class Document implements DocumentPrototype {
private String title;
private String content;
private String author;
private String cover;
private List<String> images;
@Override
public DocumentPrototype cloneDocument() {
try {
Document clone = (Document) super.clone();
// 对克隆对象的标题进行修改
clone.title = this.title + "-副本";
// 引用对象进行深拷贝
clone.images = new ArrayList<>(this.images);
return clone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
客户端调用
java
@Slf4j
public class Main {
public static void main(String[] args) {
Document document = new Document();
document.setTitle("设计模式");
document.setAuthor("dinzheng");
document.setContent("设计模式是软件开发中常用的解决方案...");
document.setCover("cover.jpg");
ArrayList<String> images = new ArrayList<>();
images.add("image1.jpg");
images.add("image2.jpg");
images.add("image3.jpg");
document.setImages(images);
Document copyDocument = (Document)document.cloneDocument();
List<String> copyDocumentImages = copyDocument.getImages();
copyDocumentImages.remove("image2.jpg");
copyDocumentImages.add("image4.jpg");
copyDocument.setImages(copyDocumentImages);
log.info("原始文档: {}", document);
log.info("copy: {}", copyDocument);
}
}
输出结果
bash
原始文档: Document(title=设计模式, content=设计模式是软件开发中常用的解决方案..., author=dinzheng, cover=cover.jpg, images=[image1.jpg, image2.jpg, image3.jpg])
copy: Document(title=设计模式-副本, content=设计模式是软件开发中常用的解决方案..., author=dinzheng, cover=cover.jpg, images=[image1.jpg, image3.jpg, image4.jpg])