Design Mode | three prototype model (shallow clone, deep clone) [PrototypePattern]

Prototype mode

Source: https://github.com/GiraffePeng/design-patterns

1. Definitions

Prototype model (Prototype Pattern) refers to a prototype to create an object instance of the specified type, and create new objects by copying the prototype.

2, application scenarios

Prototype model mainly applies to the following scenarios:

  • 1, class initialization consume more resources.
  • 2, a new object is created requires a very tedious process (data preparation, access rights, etc.)
  • 3, more complex constructor.
  • 4, produced a large number of loop object.

In Spring, prototype model is used extensively, e.g. scope = "prototype". In JSON.parseObject we often use () is also a prototype model.

3, shallow clone

For interface programming, let's create a clone interfaces PrototypeInteface.java

public interface PrototypeInteface {
	public PrototypeInteface clone();
}

PrototypeInteface create an entity class that implements the interface, override the clone method.

public class ShallowPrototype implements PrototypeInteface{

	private int id;
	
	private String name;
	
	private String type;
	
	private List<String> arr;
	
	public List<String> getArr() {
		return arr;
	}

	public void setArr(List<String> arr) {
		this.arr = arr;
	}

	public ShallowPrototype() {
		super();
	}

	public ShallowPrototype(int id, String name, String type,List<String> arr) {
		super();
		this.id = id;
		this.name = name;
		this.type = type;
		this.arr = arr;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
	@Override
	public ShallowPrototype clone() {
		ShallowPrototype shallowPrototype = new ShallowPrototype();
		shallowPrototype.setId(this.id);
		shallowPrototype.setName(this.name);
		shallowPrototype.setType(this.type);
		shallowPrototype.setArr(this.arr);
		return shallowPrototype;
	}
}

Create a test class:

public class PrototypeTest {

	public static void main(String[] args) {
		ShallowPrototype shallowPrototype = new ShallowPrototype(1, "name", "type",new ArrayList<String>() {{
			add("测试");
		}});
		ShallowPrototype clone = shallowPrototype.clone();
		System.out.println(shallowPrototype.getName() == clone.getName());
		System.out.println(shallowPrototype.getArr() == clone.getArr());
		clone.getArr().add("修改");
		List<String> arr = shallowPrototype.getArr();
		for (String string : arr) {
			System.out.println(string);
		}
	}
}

Print this console to perform post:

true
true
测试
修改

From the test results referenced address arr set is the same, meaning that replication is not a value, but address references. In this case, arr reference value data types, shallowPrototype and clone the (List) will change if we change any of the object. This is what we often say that the shallow clone. Just a complete copy of the data values, there is no reference to the object itself is copied to create a new reference object. In other words, all of the referenced objects still point to the original object.

JDK also provides a default method of Object clone, the requirements can be implemented simply cloned Cloneable interface classes, clone write method, calling super.clone shallow clone can be realized, for example:

//实现Cloneable接口
public class PrototypeClone implements Cloneable{

	private int id;
	
	private String name;
	
	private String type;
	
	private List<String> arr;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public List<String> getArr() {
		return arr;
	}

	public void setArr(List<String> arr) {
		this.arr = arr;
	}

	public PrototypeClone(int id, String name, String type, List<String> arr) {
		super();
		this.id = id;
		this.name = name;
		this.type = type;
		this.arr = arr;
	}
	
	public PrototypeClone clone() {
		try {
			//调用super.clone方法
			return (PrototypeClone) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}

Create a test class:

public class TestJdkClone {

	public static void main(String[] args) {
		PrototypeClone prototypeClone = new PrototypeClone(1, "123", "1", new ArrayList<String>() {{add("ceshi");}});
		PrototypeClone clone = prototypeClone.clone();
		System.out.println(prototypeClone.getArr() == clone.getArr());
	}
}

Print Results:

true

DESCRIPTION clone JDK shallow clone is also provided.

4, deep cloning

Deep clone clone is only a target value, rather than cloned reference address, corresponding to a spatial distribution reopened one of the objects in the heap memory properties.
Our implementation can be achieved using serialization and de-serialization.
Also create an interface:

public interface DeepCloneInterface {
	public Object cloneObject();
}

Create an implementation class, and achieve DeepCloneInterface Serializable interface (for deserialization)

public class DeepPrototype implements DeepCloneInterface,Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private int id;
	
	private String name;
	
	private List<String> arr;
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public List<String> getArr() {
		return arr;
	}

	public void setArr(List<String> arr) {
		this.arr = arr;
	}
	 
	//序列化与反序列化实现深克隆
	@Override
	public Object cloneObject() {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			
			oos.writeObject(this);
			ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bis);
			Object readObject = ois.readObject();
			
			ois.close();
			bis.close();
			oos.flush();
			oos.close();
			bos.close();
			return readObject;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}

Test categories:

public class DeepTest {

	public static void main(String[] args) {
		DeepPrototype deepPrototype = new DeepPrototype();
		deepPrototype.setArr(new ArrayList<String>() {{add("测试");}});
		deepPrototype.setId(1);
		deepPrototype.setName("测试");
		
		
		DeepPrototype cloneObject = (DeepPrototype)deepPrototype.cloneObject();
		
		System.out.println(cloneObject.getArr() == deepPrototype.getArr());
	}
}

Print Results:

false

Can be seen under a deep clone, clone only a value, and to clone does not reference types are assigned.

5, clone damage singleton

If the object of our goals is to clone singleton object, that means that cloning will undermine the deep single case. In fact prevent a single case of damage cloning Solutions is very simple, deep ban cloning can. Either a singleton class does not implement Cloneable interface; or we rewrite clone () method to return the object to the single embodiment clone method, as follows:

....
@Override
protected Object clone() {
	return 具体的单例实例对象;
}
....
Published 21 original articles · won praise 2 · Views 7498

Guess you like

Origin blog.csdn.net/qq_35551089/article/details/100099673