3. Prototype mode of design mode (shallow copy/deep copy)

Prototype mode of design mode

table of Contents

Prototype mode of design mode

1. Prototype mode-basic introduction

2. The problem of cloned sheep in prototype mode (shallow copy)

2.1. The problem of cloned sheep

2.2, shallow copy

3. Deep copy of in-depth exploration

3.1 Basic introduction to deep copy

3.2. Deep copy implementation method 1: rewrite the clone method to achieve deep copy (not recommended)

3.3. Deep copy implementation mode 2: Deep copy through object serialization (recommended)

Four, the notes and details of the prototype mode


1. Prototype mode-basic introduction

basic introduction

1) Prototype mode (Prototype mode) refers to: use prototype instances to specify the types of objects to be created, and create new objects by copying these prototypes

2) Prototype mode is a creational design mode that allows one object to create another customizable object without knowing the details of how to create it

3) The working principle is: by passing a prototype object to the object to be created, the object to be created is created by requesting the prototype object to copy itself, that is, object.clone()

4) Image understanding: Sun Dasheng pulls out the monkey hair and transforms other Sun Dasheng

Ideas

Idea: The Object class in Java is the root class of all classes. The Object class provides a clone() method, which can copy a Java object, but the Java class that needs to implement clone must implement an interface Cloneable, the interface Indicates that the class can be copied and has the ability to copy => prototype mode

 

2. The problem of cloned sheep in prototype mode (shallow copy)

2.1. The problem of cloned sheep

Now there is a sheep named Tom, name: tom, age: 1, color: white, please write a program to create 10 sheep with exactly the same attributes as tom.

The kind of sheep, and the sheep has a pig friend

And rewrite the clone method

public class Sheep implements Cloneable {
	private String name; //名字
	private int age;  //年龄
	private String color; //颜色
	private String address = "蒙古羊"; //类型
	public Pig friend; //是对象, 克隆是会如何处理
	public Sheep(String name, int age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	@Override
	public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";
	}
	//克隆该实例,使用默认的clone方法来完成
	@Override
	protected Object clone()  {
		
		Sheep sheep = null;
		try {
			sheep = (Sheep)super.clone();
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e.getMessage());
		}
		// TODO Auto-generated method stub
		return sheep;
	}
	
	
}

Pigs:

public class Pig implements Cloneable{
    private String name;
    private int age;

    public Pig(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

test:

public class Client {

	public static void main(String[] args) {
		Sheep sheep = new Sheep("tom", 1, "白色");
		
		sheep.friend = new Pig("jack",2);
		
		Sheep sheep2 = (Sheep)sheep.clone(); //��¡
		Sheep sheep3 = (Sheep)sheep.clone(); //��¡
		Sheep sheep4 = (Sheep)sheep.clone(); //��¡
		Sheep sheep5 = (Sheep)sheep.clone(); //��¡
		
		System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());
		System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode());
		System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode());
		System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode());
	}

}

Result analysis:

The hashcode of all pig friends of the lamb is the same

It can be seen that the frend of the sheep is not cloned, but points to the same object, which is a shallow copy

2.2, shallow copy

1) For a member variable whose data type is a basic data type, shallow copy will directly pass the value, that is, copy the attribute value to a new object.

2) For a member variable whose data type is a reference data type, for example, the member variable is an array, an object of a certain class, etc., then the shallow copy will be passed by reference, that is, only the reference value (memory address) of the member variable ) Make a copy for the new object . Because in fact the member variables of the two objects all point to the same instance. In this case, modifying the member variable in one object will affect the value of the member variable in another object

3) The sheep we cloned earlier is a shallow copy

4) Shallow copy is to use the default clone() method to realize sheep = (Sheep) super.clone();

3. Deep copy of in-depth exploration

3.1 Basic introduction to deep copy

1) Copy the member variable values ​​of all basic data types of the object

2) Apply for storage space for all member variables of the reference data type, and copy the object referenced by each member variable of the reference data type until all objects reachable by the object. In other words, a deep copy of an object requires a copy of the entire object

3) Deep copy implementation method 1: Rewrite the clone method to achieve deep copy

4) Deep copy implementation method 2: Deep copy through object serialization (recommended)

3.2. Deep copy implementation method 1: rewrite the clone method to achieve deep copy (not recommended)

Pig friend rewrites clone method

public class Pig implements Cloneable{
    private String name;
    private int age;

    public Pig(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Object clone() {
        Pig pig = null;
        try {
            pig= (Pig) super.clone();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

        return pig;
    }
}

And the lamb is processed separately for frend in the clone method

package clone;




public class Sheep implements Cloneable {
	private String name;
	private int age;
	private String color;
	private String address = "蒙古羊";
	public Pig friend;
	public Sheep(String name, int age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	
	@Override
	public String toString() {
		return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";
	}

	@Override
	protected Object clone()  {
		
		Sheep sheep = null;
		try {
			sheep = (Sheep)super.clone();
			//对引用数据类型单独处理
			sheep.friend= (Pig) friend.clone();
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e.getMessage());
		}
		// TODO Auto-generated method stub
		return sheep;
	}
	
	
}

test:

In this way, every lamb’s pig friend is also cloned

3.3. Deep copy implementation mode 2: Deep copy through object serialization (recommended)

Pig friend realization

Serializable接口
import java.io.Serializable;

/**
 * @author Liu
 * @date 2021/2/24 - 16:00
 */
public class Pig implements Cloneable, Serializable {
    private String name;
    private int age;

    public Pig(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Object clone() {
        Pig pig = null;
        try {
            pig= (Pig) super.clone();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

        return pig;
    }
}

Lamb implements the Serializable interface, and the deepClone method uses the object serial number to implement deep copy

import java.io.*;

public class Sheep implements Cloneable, Serializable {
	private String name;
	private int age;
	private String color;
	private String address = "蒙古羊";
	public Pig friend;
	public Sheep(String name, int age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	
	@Override
	public String toString() {
		return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";
	}

	@Override
	protected Object clone()  {
		
		Sheep sheep = null;
		try {
			sheep = (Sheep)super.clone();
			//对引用数据类型单独处理
			sheep.friend= (Pig) friend.clone();
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e.getMessage());
		}
		// TODO Auto-generated method stub
		return sheep;
	}

	//深拷贝 - 方式2 通过对象的序列化实现 (推荐)

	public Object deepClone() {

		//创建流对象
		ByteArrayOutputStream bos = null;
		ObjectOutputStream oos = null;
		ByteArrayInputStream bis = null;
		ObjectInputStream ois = null;

		try {

			//序列化
			bos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bos);
			oos.writeObject(this); //当前这个对象以对象流的方式输出

			//反序列化
			bis = new ByteArrayInputStream(bos.toByteArray());
			ois = new ObjectInputStream(bis);
			Sheep copyObj = (Sheep)ois.readObject();

			return copyObj;

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return null;
		} finally {
			//关闭流
			try {
				bos.close();
				oos.close();
				bis.close();
				ois.close();
			} catch (Exception e2) {
				// TODO: handle exception
				System.out.println(e2.getMessage());
			}
		}

	}
	
}

test

public class Client {

	public static void main(String[] args) {
		Sheep sheep = new Sheep("tom", 1, "白色");
		
		sheep.friend = new Pig("jack",2);

		//方式2 完成深拷贝
		Sheep sheep6 = (Sheep)sheep.deepClone(); //��¡
		Sheep sheep7 = (Sheep)sheep.deepClone(); //��¡
		Sheep sheep8 = (Sheep)sheep.deepClone(); //��¡
		Sheep sheep9 = (Sheep)sheep.deepClone(); //��¡

		System.out.println("sheep2 =" + sheep6 + "sheep2.friend=" + sheep6.friend.hashCode());
		System.out.println("sheep3 =" + sheep7 + "sheep3.friend=" + sheep7.friend.hashCode());
		System.out.println("sheep4 =" + sheep8 + "sheep4.friend=" + sheep8.friend.hashCode());
		System.out.println("sheep5 =" + sheep9 + "sheep5.friend=" + sheep9.friend.hashCode());



	}

}

result:

Deep copy successfully completed

Fourth, the source code analysis of the prototype mode in spring

Configure bean.xml

<bean id="id01" class="com.atguigu.spring.bean.Monster" scope="prototype"/>

Get this object in test

ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("beans.xml");
//获取monster[通过id获取monster]
Object bean = applicationContext.getBean("id01");
System.out.println("bean" + bean);

In the spring source code, scope="prototype" uses the prototype mode

Check whether it is a singleton bean in doGetBean

Five, the notes and details of the prototype mode

1) When creating a new object is more complicated, you can use the prototype mode to simplify the creation process of the object and improve efficiency at the same time

2) No need to reinitialize the object, but dynamically obtain the runtime state of the object

3) If the original object changes (increase or decrease attributes), other cloned objects will also change accordingly, no need to modify the code

4) Complicated code may be required when implementing deep cloning

5) Disadvantages: It is necessary to equip each class with a clone method, which is not difficult for a brand-new class, but when transforming an existing class, you need to modify its source code, which violates the ocp principle. Please classmates for this. We pay attention.

Guess you like

Origin blog.csdn.net/qq_45072383/article/details/114024467