1. 引言
1.1 背景
在实际编程中,有时需要频繁创建多个相似但稍有不同的对象。如果采用传统的对象创建方式,容易造成代码冗余,对象重复初始化操作也可能带来大量的的资源消耗(如时间、内存等)。这样不仅降低了灵活性,导致难以适应状态的变化,还降低了代码的可扩展性。
public class Demo {
public static void main(String[] args) {
// 创建原型对象
A a = getA();
B b = new B();
b.setParam(a.getParam());
// ...
System.out.println("B: " + b);
C c = new C();
c.setPartam(b.getPartam());
// ...
System.out.println("C: " + c);
}
}
在面向对象编程的世界里,为了帮助开发者写出更高质量、更易于维护代码的一套解决方案。针对此类问题的,提供了原型模式。原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有实例来创建新对象,避免了重复的初始化操作。适用于对象的创建过程昂贵、复杂或者外部变化频繁的情况。在需要快速创建复杂对象副本的业务中,可以通过原型模式避免每次都重新初始化所带来的开销。
1.2 目的
本文将详细介绍原型模式的基本概念、实现步骤。通过本篇文章,你将能够理解原型模式的工作原理,并学会如何在实际项目中有效地利用它。
2. 何为原型模式?
一句话概括,就是使用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。
2.1 原型模式的目的
原型模式的核心目的是通过复制现有的对象来创建新对象,从而避免昂贵的对象创建过程。这在某些场景下尤为有用,例如:
创建成本高:对象的创建成本(如时间、资源)非常高。
复杂对象:对象有很多复杂的结构,初始化过程复杂且耗时。
需要创建多个相似对象:频繁需要创建多个相似但稍有不同的对象。
2.2 原型模式适合的场景
- 对象重复创建:在需要频繁创建类似对象并减少初始化开销的场景下。
- 对象初始化复杂:对象的创建过程涉及大量计算或资源分配,通过克隆可以避免这些开销。
- 不同配置的对象:需要创建多个配置类似但具体值不同的对象时,通过克隆基准对象进行调整。
2.3 为什么不直接使用Clone方法复制类?
直接在需要复制的类中调用 clone 方法当然是简单的实现方式,但也有一些局限性:
- 破坏封装:直接调用 clone 方法可能会破坏类的封装,导致类内部的实现细节暴露。
- 不支持多态性:使用接口或抽象类,有助于处理多个不同类型的对象。用户可以通过接口调用 clone 方法,从而实现多态性,而直接调用 clone 方法无法做到这一点。
- 可能需要深拷贝:有些对象需要深拷贝(对引用类型的成员进行拷贝),直接的 clone 方法可能无法满足这一需求。通过接口或抽象类可以更灵活地实现深拷贝逻辑。
2.4 浅拷贝和深拷贝&原型模式的关联
在讨论原型模式时,深拷贝和浅拷贝是两个非常重要的概念。它们与原型模式密切相关,因为原型模式涉及到对象的复制,而对象的复制又可以分为浅拷贝和深拷贝两种方式。
何为浅拷贝?
浅拷贝(Shallow Copy)在对象复制过程中,只复制对象的基本数据类型字段,对于引用类型字段,只复制引用,不复制引用对象本身。这意味着浅拷贝后的新对象与原对象共享相同的引用对象。在 Java 中,可以使用 Object 类的 clone 方法来实现浅拷贝。默认的 clone 方法进行的是浅拷贝:
public class ShallowCopyExample implements Cloneable {
private int value;
private int[] array;
public ShallowCopyExample(int value, int[] array) {
this.value = value;
this.array = array;
}
@Override
protected ShallowCopyExample clone() {
try {
return (ShallowCopyExample) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
// Getters and setters...
public static void main(String[] args) {
int[] array = {1, 2, 3};
ShallowCopyExample original = new ShallowCopyExample(42, array);
ShallowCopyExample cloned = original.clone();
System.out.println("初始的数组: " + original.getArray()[0]); // 1
System.out.println("克隆对象的数组: " + cloned.getArray()[0]); // 1
// 修改克隆对象的数组
cloned.getArray()[0] = 99;
System.out.println("初始的数组: " + original.getArray()[0]); // 99
System.out.println("克隆对象的数组: " + cloned.getArray()[0]); // 99
}
}
如上所示,修改克隆对象的数组会影响原始对象的数组,这是因为它们共享相同的引用。
何为深拷贝?
深拷贝(Deep Copy)在对象复制过程中,除了复制对象的基本数据类型字段,还递归复制引用类型字段所引用的对象。这意