原型模式(Prototype Pattern)是一种创建型设计模式,其主要目的是通过复制(克隆)现有对象来创建新对象,而无需显式地使用构造函数创建新对象。这种模式通常用于创建成本较高或复杂的对象,以避免重复的初始化工作。
clone
方法,用于复制对象。所有需要支持克隆操作的类都需要实现这个接口。clone
方法来克隆自身。原型模式可以分为浅克隆和深克隆两种形式,取决于复制的方式。
Java中的Object类中提供了clone()方法来实现浅克隆。
class Prototype implements Cloneable{
public Prototype() {
System.out.println("创建具体的原型对象");
}
@Override
protected Prototype clone() throws CloneNotSupportedException {
System.out.println("复制成功!");
return (Prototype) super.clone();
}
}
public class PrototypeDemo {
public static void main(String[] args) throws CloneNotSupportedException{
Prototype original = new Prototype();
Prototype clone = original.clone();
System.out.println(original == clone); //false
}
}
上面的方法很简单,当然,还有另外一种方法,就是自己创建原型接口,按照上面的原型模式的结构来实现
// 原型接口
interface Prototype {
Prototype clone();
}
// 具体原型类
class ConcretePrototype implements Prototype {
private String data;
public ConcretePrototype(String data) {
this.data = data;
}
@Override
public Prototype clone() {
return new ConcretePrototype(this.data);
}
public String getData() {
return data;
}
}
public class PrototypeDemo {
public static void main(String[] args) {
// 创建一个具体原型对象
Prototype original = new ConcretePrototype("Hello, world!");
// 克隆原型对象来创建新对象
Prototype clone = original.clone();
// 输出原型和克隆对象的数据
System.out.println("Original Data: " + ((ConcretePrototype) original).getData());
System.out.println("Clone Data: " + ((ConcretePrototype) clone).getData());
}
}
原型模式使用场景有:
对象的创建成本较高:如果创建一个对象的成本很高,例如需要从数据库中加载大量数据或进行复杂的计算,那么使用原型模式可以避免多次创建相同的对象,而是通过克隆已有对象来创建新对象,从而提高性能。
对象的创建过程复杂:当对象的创建过程非常复杂,包括多个步骤或依赖于其他对象时,使用原型模式可以简化代码,因为您只需克隆一个已有对象,而不必重复执行复杂的创建步骤。
需要保持对象的不变性:有些对象需要保持不变性,即不能通过直接赋值属性的方式修改其状态。原型模式可以帮助您创建对象的副本,而不会影响原始对象的状态。
大量相似对象的创建:当需要创建大量相似但略有差异的对象时,原型模式非常有用。您可以创建一个原型对象,然后根据需要克隆该对象并进行适当的修改。
支持动态配置对象:原型模式允许您在运行时动态配置对象,通过克隆已有对象并进行修改,而不必硬编码不同的配置选项。
减少子类的创建:在某些情况下,如果您有多个子类,而这些子类只有一些差异,可以使用原型模式来创建这些子类的实例,而不必为每个子类都创建一个独立的类。
在实现深克隆时,有几种常见的方式:
class Address implements Cloneable {
private String street;
private String city;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Address(String street, String city) {
this.street = street;
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
private String name;
private Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
Person clonedPerson = (Person) super.clone();
clonedPerson.address = (Address) address.clone();
return clonedPerson;
}
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("步行街", "北京");
Person originalPerson = new Person("Alice", address);
Person clonedPerson = (Person) originalPerson.clone();
System.out.println(originalPerson.getName()+" "+originalPerson.getAddress().getStreet()); // Alice 步行街
clonedPerson.setName("Bob");
clonedPerson.getAddress().setStreet("人民公园");
System.out.println(clonedPerson.getName()+" "+clonedPerson.getAddress().getStreet()); // Bob 人民公园
}
}
import java.io.*;
class Address implements Serializable {
private String street;
private String city;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Address(String street, String city) {
this.street = street;
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Serializable {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
private String name;
private Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
Person clonedPerson = (Person) super.clone();
clonedPerson.address = (Address) address.clone();
return clonedPerson;
}
}
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Address address = new Address("步行街", "北京");
Person originalPerson = new Person("Alice", address);
// 序列化主类
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(originalPerson);
// 反序列化创造克隆类
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Person clonedPerson = (Person) ois.readObject();
System.out.println(originalPerson.getName()+" "+originalPerson.getAddress().getStreet()); // Alice 步行街
clonedPerson.setName("Bob");
clonedPerson.getAddress().setStreet("人民公园");
System.out.println(clonedPerson.getName()+" "+clonedPerson.getAddress().getStreet()); // Bob 人民公园
}
}