什么是原型模式?
原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而不是通过实例化类来创建。这种模式特别适用于创建复杂对象或创建成本较高的情况。
为什么使用原型模式?
- 避免重复创建对象的开销
- 动态创建对象的类型
- 避免构造函数的约束
- 保持对象的状态
实现方式
在Java中,我们通常通过实现Cloneable接口来实现原型模式。
基本实现
public class Prototype implements Cloneable {
private String field;
public Prototype(String field) {
this.field = field;
}
@Override
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
// getter和setter
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}浅克隆与深克隆
1. 浅克隆示例
public class ShallowPrototype implements Cloneable {
private String name;
private List<String> list;
public ShallowPrototype(String name, List<String> list) {
this.name = name;
this.list = list;
}
@Override
public ShallowPrototype clone() {
try {
return (ShallowPrototype) super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
// getters and setters
public List<String> getList() {
return list;
}
}2. 深克隆示例
public class DeepPrototype implements Cloneable {
private String name;
private List<String> list;
public DeepPrototype(String name, List<String> list) {
this.name = name;
this.list = list;
}
@Override
public DeepPrototype clone() {
try {
DeepPrototype clone = (DeepPrototype) super.clone();
// 深克隆List
clone.list = new ArrayList<>(this.list);
return clone;
} catch (CloneNotSupportedException e) {
return null;
}
}
// getters and setters
public List<String> getList() {
return list;
}
}使用序列化实现深克隆
public class SerializablePrototype implements Serializable {
private String name;
private List<String> list;
public SerializablePrototype(String name, List<String> list) {
this.name = name;
this.list = list;
}
public SerializablePrototype deepClone() {
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 (SerializablePrototype) ois.readObject();
} catch (Exception e) {
return null;
}
}
}实际应用示例
1. 文档克隆系统
public class Document implements Cloneable {
private String title;
private String content;
private List<String> authors;
private Map<String, String> metadata;
public Document(String title, String content) {
this.title = title;
this.content = content;
this.authors = new ArrayList<>();
this.metadata = new HashMap<>();
}
@Override
public Document clone() {
try {
Document clone = (Document) super.clone();
// 深克隆集合
clone.authors = new ArrayList<>(this.authors);
clone.metadata = new HashMap<>(this.metadata);
return clone;
} catch (CloneNotSupportedException e) {
return null;
}
}
// 创建模板文档
public static Document createTemplate(String type) {
Document template = new Document("Template", "");
switch (type) {
case "report":
template.setMetadata("type", "report");
template.setMetadata("format", "pdf");
break;
case "letter":
template.setMetadata("type", "letter");
template.setMetadata("format", "doc");
break;
}
return template;
}
// getters and setters
public void setMetadata(String key, String value) {
metadata.put(key, value);
}
}2. 使用示例
public class Client {
public static void main(String[] args) {
// 创建报告模板
Document reportTemplate = Document.createTemplate("report");
// 基于模板创建新文档
Document report1 = reportTemplate.clone();
report1.setTitle("2024年第一季度报告");
Document report2 = reportTemplate.clone();
report2.setTitle("2024年第二季度报告");
// 创建信件模板
Document letterTemplate = Document.createTemplate("letter");
// 基于模板创建新信件
Document letter1 = letterTemplate.clone();
letter1.setTitle("商务邀请函");
}
}原型模式的优点
- 减少对象创建的开销
- 动态添加和删除产品
- 提供更灵活的实例化机制
- 避免重复初始化代码
原型模式的缺点
- 克隆复杂对象或循环引用的对象比较困难
- 深克隆和浅克隆的选择可能会影响系统
- 必须实现克隆方法
适用场景
- 需要创建大量相似对象的场景
- 对象创建成本较高的场景
- 需要保持对象状态的场景
- 需要避免重复初始化的场景
与其他模式的关系
- 工厂模式:原型模式可以与工厂模式结合使用
- 命令模式:可以使用原型模式来保存命令的状态
- 备忘录模式:可以使用原型模式来实现对象状态的保存和恢复
总结
原型模式是一种简单且强大的创建型设计模式,它通过克隆现有对象来创建新对象,避免了重复创建对象的开销。在实际应用中,需要注意深克隆和浅克隆的选择,以及处理复杂对象克隆的问题。
参考资料
- 《Design Patterns: Elements of Reusable Object-Oriented Software》
- 《Effective Java》第三版
- Java API 文档
- Spring Framework 源码

