6.原型模式

发布时间:2024年01月05日


一、深拷贝和浅拷贝

1、浅拷贝

定义

浅拷贝是指在拷贝对象时,只复制对象本身以及对象中的基本数据类型字段,而不复制引用类型字段。因此,浅拷贝产生的新对象和原对象共享引用类型字段的内容。

代码

//地址
class Address {
    private String city;

    public Address(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

//人
class Person implements Cloneable {
    private Integer age;
    private String name;
    private Address address;

    public Person(Integer age, String name, Address address) {
        this.age = age;
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class ShallowCopyPrototypeExample {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address originalAddress = new Address("广州");
        Person originalPerson = new Person(18, "John", originalAddress);

        // 浅拷贝
        Person clonedPerson = (Person) originalPerson.clone();

        // 修改拷贝对象的值
        clonedPerson.setAge(20);
        clonedPerson.setName("Jane");
        clonedPerson.getAddress().setCity("深圳");

        // 输出原来对象的值
        System.out.println("Original Person Age: " + originalPerson.getAge());  // Output: 18
        System.out.println("Original Person Name: " + originalPerson.getName());  // Output: John
        System.out.println("Original Person Address City: " + originalPerson.getAddress().getCity());  // Output: 深圳
    }
}

通过上面的代码输出,我们可以看到Age还是原来的18,说明基本对象是重新复制了一个,但是Address变成了我们修改后的值,可以证明他们是同一个引用的。

而至于为什么 String 类型没有变化,大家可以看我另外一个文章new String()创建了几个对象?,由于Java中 String 对象的不可变性,对 String 对象进行修改实际上是创建了一个新的 String 对象,而原来的对象保持不变。

2、深拷贝

定义

深拷贝是指在拷贝对象时,不仅复制对象本身,还复制对象中引用类型字段所指向的对象,从而产生一个全新的对象,原对象和新对象的引用类型字段互不影响。

在Java中,实现深拷贝的方式有多种,其中包括手动实现、使用序列化、使用第三方库等。一种常见的方式是通过对象的序列化和反序列化来实现深拷贝。

代码

/**
 * 工具类,通过序列化和反序列化,创建了新的对象
 */
class DeepCopyUtil {
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T deepCopy(T object) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(object);

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bis);
        return (T) in.readObject();
    }
}

class DeepCopyAddress implements Serializable {
    private String city;

    public DeepCopyAddress(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

class DeepCopyPerson implements Serializable {
    private String name;
    private DeepCopyAddress address;

    public DeepCopyPerson(String name, DeepCopyAddress address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public DeepCopyAddress getAddress() {
        return address;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class DeepCopyPrototypeExample {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        DeepCopyAddress originalAddress = new DeepCopyAddress("广州");
        DeepCopyPerson originalPerson = new DeepCopyPerson("John", originalAddress);

        // 深拷贝
        DeepCopyPerson clonedPerson = DeepCopyUtil.deepCopy(originalPerson);

        // 修改拷贝对象的值
        clonedPerson.setName("Jane");
        clonedPerson.getAddress().setCity("深圳");

        // 输出原来对象的值
        System.out.println("Original Person Name: " + originalPerson.getName());  // Output: John
        System.out.println("Original Person Address City: " + originalPerson.getAddress().getCity());  // Output: 广州
    }
}

二、原型模式

原型模式其主要目的是通过复制现有对象来创建新的对象,而不是通过实例化类。通过克隆(或复制)一个现有对象,我们可以获得一个新对象,新对象与原对象具有相同的属性和状态。这样做的一个主要好处是避免了直接调用构造函数,从而提高了对象的创建效率。

结构图

原型模式结构图

代码

class Address implements Cloneable {
    private String city;

    public Address(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Person implements Cloneable {
    private String name;
    private Address address;

    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public Address getAddress() {
        return address;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 使用浅拷贝
        Person clonedPerson = (Person) super.clone();

        // 对引用类型字段进行拷贝
        clonedPerson.address = (Address) address.clone();

        return clonedPerson;
    }
}

public class ShallowCopyPrototypeExample {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address originalAddress = new Address("广州");
        Person originalPerson = new Person("John", originalAddress);

        // 使用浅拷贝创建新对象
        Person clonedPerson = (Person) originalPerson.clone();

        // 修改克隆对象的属性
        clonedPerson.setName("Jane");
        clonedPerson.getAddress().setCity("深圳");

        // 输出原型对象和克隆对象的属性
        System.out.println("Original Person Name: " + originalPerson.getName());  // Output: John
        System.out.println("Original Person Address City: " + originalPerson.getAddress().getCity());  // Output: San Francisco
    }
}


总结

上面我们介绍了浅拷贝和深拷贝,这是我们用来实现原型模式的手段,然后当我们遇到下面几种场景时,可以考虑用原型模式

  1. 克隆对象:当需要创建一个新对象,而这个对象的属性值可以从现有对象复制而来时,原型模式是一种常见的选择。
  2. 避免构造函数的复杂性:有些对象的构造过程较为复杂,而克隆操作可以避免直接调用构造函数,提高效率。
  3. 对象的状态变化较小:原型模式适用于对象的状态变化较小的情况,因为克隆是基于原对象的一个拷贝,如果状态变化较大,可能还需要做一些后续处理。
文章来源:https://blog.csdn.net/csdn15917204572/article/details/135365642
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。