Prototype mode-shallow clone and deep clone

Overview

Use an already created instance as a prototype, and create a new object that is the same as the prototype object by copying the prototype object.

 structure

The prototype model includes the following roles:

  • Abstract prototype class: specifies the clone() method that the concrete prototype object must implement.
  • Concrete prototype class: implements the clone() method of the abstract prototype class, which is an object that can be copied.
  • Access class: Use the clone() method in the concrete prototype class to copy the new object.

The interface class diagram is as follows:

achieve

Prototype cloning is divided into shallow cloning and deep cloning

Shallow clone: ​​Create a new object. The properties of the new object are exactly the same as the original object. For non-basic type properties, it still points to the memory address of the object pointed to by the original property.

Deep clone: ​​Create a new object, other objects referenced in the attribute will also be cloned, and no longer point to the original object address.

The Object class inclone() Java provides   methods to implement shallow cloning .

The Cloneable interface is the abstract prototype class in the above class diagram, and the sub-implementation class that implements the Cloneable interface is the concrete prototype class.

code show as below:

Realizetype (specific prototype class):

Realizetype.java

package com.itheima.pattern.prototype.demo;

/**
 * @version v1.0
 * @ClassName: Realizetype
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class Realizetype implements Cloneable {

    public Realizetype() {
        System.out.println("具体的原型对象创建完成!");
    }

    @Override
    public Realizetype clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");

        return (Realizetype) super.clone();
    }
}

client.java

package com.itheima.pattern.prototype.demo;

/**
 * @version v1.0
 * @ClassName: client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class client {
    public static void main(String[] args) throws CloneNotSupportedException {
        //创建一个原型类对象
        Realizetype realizetype = new Realizetype();

        //调用Realizetype类中的clone方法进行对象的克隆
        Realizetype clone = realizetype.clone();

        System.out.println("原型对象和克隆出来的是否是同一个对象?" + (realizetype == clone));
    }
}



Case

Use the prototype model to generate the "three good students" certificate

The "three good students" certificates of the same school are the same except for the names of the winners.

You can use the prototype mode to copy multiple "three good students" award certificates, and then modify the name on the award certificate.

The class diagram is as follows:

Citation.java

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: Citation
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class Citation implements Cloneable {

    //三好学生上的姓名
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }

    public void show() {
        System.out.println(name + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}

CitaionTest.java

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: CitaionTest
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class CitaionTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation c1 = new Citation();
        c1.setName("张三");

        //复制奖状
        Citation c2 = c1.clone();
        //将奖状的名字修改李四
        c2.setName("李四");

        c1.show();
        c2.show();
    }
}



scenes to be used

  • The creation of objects is very complicated, you can use the prototype mode to quickly create objects.
  • Performance and safety requirements are relatively high.


Extension (deep clone)

Modify the name attribute of the Citation class in the case of the "three good students" certificate above to the attribute of the Student type.

Shallow clone

code show as below:

Student.java

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: Student
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class Student {

    //学生的姓名
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

Citation.java

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: Citation
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class Citation implements Cloneable {

    private Student stu;

    public Student getStu() {
        return stu;
    }

    public void setStu(Student stu) {
        this.stu = stu;
    }

    @Override
    public Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }

    public void show() {
        System.out.println(stu.getName() + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}

CitaionTest.java

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: CitaionTest
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class CitaionTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        //1,创建原型对象
        Citation citation = new Citation();
        //创建张三学生对象
        Student stu = new Student();
        stu.setName("张三");
        citation.setStu(stu);

        //2,克隆奖状对象
        Citation citation1 = citation.clone();
        Student stu1 = citation1.getStu();
        stu1.setName("李四");

        //3,调用show方法展示
        citation.show();
        citation1.show();
    }
}



Description:

The stu object and the stu1 object are the same object, and the name attribute value in the stu1 object will be changed to "Li Si", and the two Citation objects are all Li Si.

This is the effect of shallow cloning, which copies the attributes of the reference type in the concrete prototype class (Citation).

This situation requires the use of deep cloning, and deep cloning requires the use of object streams . code show as below:

Student.java

package com.itheima.pattern.prototype.test1;

import java.io.Serializable;

/**
 * @version v1.0
 * @ClassName: Student
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class Student implements Serializable {

    //学生的姓名
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

Citation.java

package com.itheima.pattern.prototype.test1;

import java.io.Serializable;

/**
 * @version v1.0
 * @ClassName: Citation
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class Citation implements Cloneable, Serializable {

    private Student stu;

    public Student getStu() {
        return stu;
    }

    public void setStu(Student stu) {
        this.stu = stu;
    }

    @Override
    public Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }

    public void show() {
        System.out.println(stu.getName() + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}

CitaionTest.java

package com.itheima.pattern.prototype.test1;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * @version v1.0
 * @ClassName: CitaionTest
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class CitaionTest {
    public static void main(String[] args) throws Exception {
        //1,创建原型对象
        Citation citation = new Citation();
        //创建张三学生对象
        Student stu = new Student();
        stu.setName("张三");
        citation.setStu(stu);

        //创建对象输出流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\iadai\\Desktop\\a.txt"));
        //写对象
        oos.writeObject(citation);
        //释放资源
        oos.close();

        //创建对象输入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\iadai\\Desktop\\a.txt"));
        //读取对象
        Citation citation1 = (Citation) ois.readObject();
        //释放资源
        ois.close();
        Student stu1 = citation1.getStu();
        stu1.setName("李四");

        citation.show();
        citation1.show();
    }
}



Note: Citation class and Student class must implement Serializable interface, otherwise NotSerializableException will be thrown.

Guess you like

Origin blog.csdn.net/qq_39368007/article/details/113941295