“原型模式”(Prototype Pattern)是创建型设计模式之一,通过复制一个已有对象来创建新对象,而不是通过实例化类来创建对象。
这个模式使用了原型实例来指定创建对象的种类,并通过拷贝这些原型来生成新的对象。
一、定义(Definition)
原型模式是用于 创建重复的对象,同时又能保证性能的一种设计模式。它通过 克隆已有的实例 来生成新实例。
通俗来说:你有一个模子(原型对象),每次需要新的对象时,就“复制”一个,而不是“重新造一个”。
二、适用场景(When to Use)
- 创建对象的开销较大(如涉及数据库、网络、文件等操作)。
- 系统要 避免使用构造函数创建实例。
- 需要大量相似对象的情况。
- 对象的结构复杂,构造代价高,使用已有对象复制更高效。
三、结构图(UML)
+----------------+ +---------------------+
| Client | | Prototype |
+----------------+ +---------------------+
| - prototype |<>---->| + clone(): Prototype|
| + newObject() | +---------------------+
+----------------+ ▲
|
+--------------------+
| ConcretePrototype |
+--------------------+
| + clone(): Prototype|
+--------------------+
四、实现方式(Java 示例)
1. 定义原型接口
/**
* @Date: 2024/12/26
* 1. 原型接口
*/
public interface FilePrototype extends Cloneable {
FilePrototype clone();
}
2. 创建原型实现类
package com.myxq.创建型模式.原型模式;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @Date: 2024/12/26
* 2. 具体原型类
*/
@Data
@AllArgsConstructor
public class File implements FilePrototype {
private String name;
private int size; // 文件大小
private String content; // 文件内容
// 实现克隆方法
@Override
public FilePrototype clone() {
try {
return (FilePrototype) super.clone(); // 浅拷贝
} catch (CloneNotSupportedException e) {
throw new RuntimeException("克隆失败", e);
}
}
@Override
public String toString() {
return "File{name='" + name + "', size=" + size + ", content='" + content + "'}";
}
}
3. 客户端使用
/**
* @Date: 2024/12/26
*/
public class Client {
public static void main(String[] args) {
// 创建一个文件对象
File originalFile = new File("设计模式文档", 1024, "这是关于设计模式的详细内容。");
// 使用克隆方法创建副本
File clonedFile = (File) originalFile.clone();
// 修改克隆文件的属性
clonedFile.setName("设计模式文档 - 副本");
clonedFile.setContent("这是克隆的文档内容,修改后与原始文档不同。");
// 输出原始文件和克隆文件
System.out.println("原始文件: " + originalFile);
System.out.println("克隆文件: " + clonedFile);
}
}
五、深拷贝 vs 浅拷贝
- 浅拷贝(Shallow Copy):复制对象本身,但内部引用对象不会复制,只复制引用地址。
- 深拷贝(Deep Copy):对象以及其内部引用的对象都要复制一份。
Java 深拷贝实现方式:
- 通过序列化
ObjectOutputStream
+ObjectInputStream
。 - 手动克隆内部成员变量。
六、优缺点
优点 | 缺点 |
性能优于 new 操作,尤其是初始化成本高时 | 实现深拷贝麻烦,尤其是复杂对象嵌套时 |
可动态配置对象运行时属性 | 每个类都要实现 clone 方法,违反单一职责原则 |
避免构造函数污染客户端 | clone() 是 Object 的 protected 方法,使用需小心 |