原型模式的核心思想是通过复制现有对象来创建新的对象,而不是重新创建一个完全新对象。这种方式的优势在于避免了创建新对象的开销,并且可以让我们根据现有对象来快速生成相似的对象。
在实际应用中,我们通过以下方式来实现原型模式:
clone方法,所有的具体原型类都需要实现这个方法。clone方法,创建并返回一个新对象。克隆的方式通常有两种:浅拷贝和深拷贝。这两种方式的区别在于如何处理对象中的引用类型成员变量。
假设我们有一个Person类,它有一个引用类型的成员变量address。
class Address {
String street;
Address(String street) {
this.street = street;
}
@Override
public String toString() {
return "Address{" + "street='" + street + "'}";
}
}
class Person implements Cloneable {
String name;
Address address;
Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
public Person clone() {
try {
// 浅拷贝:直接调用super.clone(),复制原对象的基本属性
Person cloned = (Person) super.clone();
return cloned;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "Person{name='" + name + "', address=" + address + "}";
}
}
public class ShallowCopyTest {
public static void main(String[] args) {
Address address1 = new Address("123 Main St");
Person person1 = new Person("John", address1);
// 克隆对象
Person person2 = person1.clone();
System.out.println("Before modifying address:");
System.out.println("person1: " + person1);
System.out.println("person2: " + person2);
// 修改原始对象的地址
person1.address.street = "456 Oak St";
System.out.println("After modifying address:");
System.out.println("person1: " + person1);
System.out.println("person2: " + person2); // person2的address也会被修改
}
}输出:
Before modifying address:
person1: Person{name='John', address=Address{street='123 Main St'}}
person2: Person{name='John', address=Address{street='123 Main St'}}
After modifying address:
person1: Person{name='John', address=Address{street='456 Oak St'}}
person2: Person{name='John', address=Address{street='456 Oak St'}}在上面的代码中,person1和person2共享了同一个address对象,因此修改person1的address也会影响到person2。
在深拷贝中,我们会手动克隆引用类型的成员变量,确保每个对象都有自己独立的address对象。
class Person implements Cloneable {
String name;
Address address;
Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
public Person clone() {
try {
// 深拷贝:先克隆基本类型属性,再手动克隆引用类型
Person cloned = (Person) super.clone();
cloned.address = new Address(this.address.street); // 深拷贝Address对象
return cloned;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "Person{name='" + name + "', address=" + address + "}";
}
}
public class DeepCopyTest {
public static void main(String[] args) {
Address address1 = new Address("123 Main St");
Person person1 = new Person("John", address1);
// 克隆对象
Person person2 = person1.clone();
System.out.println("Before modifying address:");
System.out.println("person1: " + person1);
System.out.println("person2: " + person2);
// 修改原始对象的地址
person1.address.street = "456 Oak St";
System.out.println("After modifying address:");
System.out.println("person1: " + person1);
System.out.println("person2: " + person2); // person2的address不受影响
}
}输出:
Before modifying address:
person1: Person{name='John', address=Address{street='123 Main St'}}
person2: Person{name='John', address=Address{street='123 Main St'}}
After modifying address:
person1: Person{name='John', address=Address{street='456 Oak St'}}
person2: Person{name='John', address=Address{street='123 Main St'}}在深拷贝中,修改person1的address不会影响person2,因为它们的address字段已经是独立的对象。
原型模式是一种通过克隆现有对象来创建新对象的设计模式。它在减少对象创建开销、处理复杂对象时非常有用,但需要注意克隆的实现细节(特别是浅拷贝和深拷贝的选择),以及处理引用类型的成员变量时的潜在问题。
如果您有任何问题或建议,欢迎留言讨论。