The copyright of this article belongs to the author and the blog Park, welcome to reprint, but without the consent of the author must retain this statement, and give a link to the original text in a prominent place on the page of the article, otherwise reserve the right to pursue legal responsibility.

We’ve heard the saying before: “The highest state of a programmer is Ctrl+C, Ctrl+V.” Whether this is true or not, let’s talk about the process, which we all know is copying an object and pasting it over and over again. This process can be called cloning. Another example is that we printed so many resumes when we applied.

Cloning, as we all know, is to make copies of several identical objects from one object. Similarly, in the object-oriented system, we can also use cloning technology to clone several identical objects. In the application, some objects is more complex, its creation process is too complicated, and we also need frequent use of the object, if this time we new the object according to the conventional thinking, so be sure to bring a lot of trouble, this time we want to use an existing object to continually to replicate, This is cloning in programming. Here the prototype pattern can satisfy our “clone”, in the prototype pattern we can use a prototype object to indicate the type of object we want to create, and then copy the object method to obtain the object instance of the exact same object. This is what the prototype pattern is designed for.

I. Schema definition

I. Schema definition

With this brief introduction, we can basically define the prototype pattern. The stereotype pattern is to specify what kind of objects to create with prototype instances, and to create new objects by copying these prototypes.

In the prototype pattern, the created object realizes the creation process by requesting the prototype object to copy the prototype object itself, of course, the created object needs to know the type of the prototype object. This means that the object being created only needs to know the type of the prototype object to get more prototype instance objects, and how these prototype objects are created does not matter at all.

When it comes to prototyping, we have to distinguish between two concepts: deep copy and shallow copy.

Shallow copy: Use a known instance to assign values to the member variables of the newly created instance. This method is called shallow copy.

Deep copy: When the copy constructor of a class copies not only all the non-reference member variable values of the object, but also creates new instances of the reference type’s member variables and initializes them as formal parameter instance values.

For details on deep and shallow copies, see here: Introspecting Shallow and Deep Copies of Java

Second, pattern structure

Second, pattern structure

The following is a UML diagram of the prototype pattern:

Archetypal mode consists of the following three characters:

Prototype: Abstract Prototype class. Declare the interface to clone itself. ConcretePrototype: ConcretePrototype class. To achieve the specific operation of cloning. Client: indicates the Client class. Get a new object by having a prototype clone itself.

All Java classes inherit from Object. The Object class provides a clone() method, which makes a copy of a Java Object. However, Java classes that need to implement Clone must implement one interface :Cloneable. This interface is the ability to copy and specific said, if not implement this interface and direct call clone () method will throw CloneNotSupportedException anomalies. As follows:

public class PrototypeDemo implements Cloneable{public Object clone(a){ Object object =null;try{ object =super.clone(); }catch(CloneNotSupportedException exception) {System. Err. Println ("Not support cloneable"); }return object;
    }
    ……
}
Copy the code

Any Class in Java that implements the Cloneable interface can make a copy of itself by calling the Clone () method and passing it to the caller. In general, the clone() method meets the following requirements: (1) For any object X, there is x.lone ()! =x, that is, the cloned object and the original object are not the same object. (2) For any object x, there is x.lone ().getClass()== x.getclass (), that is, the cloned object has the same type as the original object. (3) If the equals() method of object x is properly defined, x.lone ().equals(x) should be true.

Third, mode realization

Third, mode realization

 
Copy the code
public abstract class Prototype implements Cloneable {
    protected ArrayList<String> list = new ArrayList<String>();
 
    @Override
    public Object clone(a) throws CloneNotSupportedException {
        return super.clone();
    }
 
    public abstract void show(a);
}
Copy the code
  1.  
public class ShallowClone extends Prototype {
    @Override
    public Prototype clone(a){
        Prototype prototype = null;
        try {
            prototype = (Prototype)super.clone();
        }
        catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return prototype;
    }
 
    @Override
    public void show(a){
        System.out.println("Shallow clone"); }}Copy the code
public class DeepClone extends Prototype {
    @SuppressWarnings("unchecked")
    @Override
    public Prototype clone(a) {
        Prototype prototype = null;
        try {
            prototype = (Prototype)super.clone();
        }
        catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        prototype.list = (ArrayList<String>) this.list.clone();
        return prototype;
    }
 
    @Override
    public void show(a){
        System.out.println("Deep clone"); }}Copy the code
public class Client {
    public static void main(String[] args) {
        ShallowClone cp = new ShallowClone();
        ShallowClone clonecp = (ShallowClone) cp.clone();
        clonecp.show();
        System.out.println(clonecp.list == cp.list);
 
        DeepClone cp2 = newDeepClone(); DeepClone clonecp2 = (DeepClone) cp2.clone(); clonecp2.show(); System.out.println(clonecp2.list == cp2.list); }}Copy the code
Running results:Copy the code
Shallow clonetrueA deep clonefalse
Copy the code

4. Advantages and disadvantages of the mode

optimal4. Advantages and disadvantages of the modepoint

1. If creating new objects is complicated, you can use the prototype pattern to simplify the object creation process and improve efficiency.

2. You can use deep clones to preserve the state of objects.

The prototype pattern provides a simplified creation structure.

disadvantages

1. Complex code may be required to implement procloning.

2, each class needs to be equipped with a clone method, and the clone method needs to consider the function of the class, which is not very difficult for the new class, but the transformation of the existing class, is not necessarily an easy thing, must modify its source code, in violation of the “open and closed principle”.

5. Mode usage scenarios

1. If the cost of creating a new object is high, we can copy the existing object to obtain it.

2, if the system wants to save the state of the object, and the change of the state of the object is very small, or the object itself takes up little memory, you can also use the prototype mode with the memo mode to apply. On the other hand, if the object’s state changes a lot, or the object takes up a lot of memory, then the state pattern is better than the prototype pattern. 3. You need to avoid using hierarchical factory classes to create hierarchical objects where instance objects have only one or a few combined states. It may be more convenient to create a new instance by copying the prototype object rather than using a constructor to create a new instance.

6. Model summary

The prototype pattern hides the complexity of creating objects from customers. The customer only needs to know the type of object to be created and can request a new object that is exactly the same as that object without knowing the exact creation process.

2. Cloning is divided into shallow cloning and deep cloning.

3. While it is possible to use the prototype pattern to obtain a new object, sometimes object copying can be quite complex, such as deep cloning.

 

Clone method shallow copy problems:

To get a copy of an Object, use the clone() method of the Object class. The Clone method in the Object class is a shallow copy.

1. Override the clone() method of the base class in the derived class and declare it public. 2. In the clone() method of the derived class, call super.clone(). 3. Implement the Cloneable interface in derived classes.

Let’s start with the following code:

public class Person implements Cloneable{
    / * * name * * /
    private String name;
    
    /** Email **/
    private Email email;
 
    public String getName(a) {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Email getEmail(a) {
        return email;
    }
 
    public void setEmail(Email email) {
        this.email = email;
    }
    
    public Person(String name,Email email){
        this.name  = name;
        this.email = email;
    }
    
    public Person(String name){
        this.name = name;
    }
 
    protected Person clone(a) {
        Person person = null;
        try {
            person = (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        
        returnperson; }}public class Email {
	private Object name;
	private String content;
	
	public Email(Object name, String content) {
		this.name = name;
		this.content = content;
	}
 
	public String getContent(a) {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public Object getName(a) {
		return name;
	}
	public void setName(Object name) {
		this.name = name; }}public class Client {
    public static void main(String[] args) {
        // Write an email
        Email email = new Email("Please attend the meeting."."Please join us today at 12:30 in conference room 2...");
        
        Person person1 =  new Person("Zhang",email);
        
        Person person2 =  person1.clone();
        person2.setName("Bill");
        Person person3 =  person1.clone();
        person3.setName("Fifty");
        
        System.out.println(person1.getName() + "The email said:" + person1.getEmail().getContent());
        System.out.println(person2.getName() + "The email said:" + person2.getEmail().getContent());
        System.out.println(person3.getName() + "The email said:"+ person3.getEmail().getContent()); }} -------------------- Output: Zhang SAN's email content is: please contact today12:30Go to conference room 2 for a meeting... The content of Li Si's email is: Please join us today12:30Go to conference room 2 for a meeting... Wang Wu's mail content is: please and today12:30Go to conference room 2 for a meeting...Copy the code

 

In this application, first define an email, and then send the email to Three people, Three people, because they are using the same email, and only the name is different, so use the object class of three, then change the name of the object can be. There is nothing wrong with the program up to this point, but if we need to arrive 30 minutes early on Wednesday, change the content of the email:

public class Client {
    public static void main(String[] args) {
        // Write an email
        Email email = new Email("Please attend the meeting."."Please join us today at 12:30 in conference room 2...");
        
        Person person1 =  new Person("Zhang",email);
        
        Person person2 =  person1.clone();
        person2.setName("Bill");
        Person person3 =  person1.clone();
        person3.setName("Fifty");
        
        person1.getEmail().setContent("Please come to conference room 2 at 12:00 today...");
        
        System.out.println(person1.getName() + "The email said:" + person1.getEmail().getContent());
        System.out.println(person2.getName() + "The email said:" + person2.getEmail().getContent());
        System.out.println(person3.getName() + "The email said:"+ person3.getEmail().getContent()); }}Copy the code

 

Here is also the use of zhang SAN the object to achieve a copy of Li Si, Wang Wu, and finally will zhang SAN’s mail content changed to: please attend the meeting with today 12:00 to two conference room… . But as a result:

The content of Zhang SAN's email is: Please attend the meeting from 12:00 to meeting room 2 today... The content of Li Si's email is: Please attend the meeting from 12:00 to meeting room 2 today... The content of Wang Wu's email is: Please attend the meeting from 12:00 to conference room 2 today...Copy the code

 

Here we have a question why li Si and Wang Wu’s email content also changed? In fact, the key problem lies in the clone() method. We know that the clone() method uses the Clone () method of the Object class, but there is a defect in this method. It does not copy all the attributes of the Object, but selectively copies them.

(1) Basic types:

If the variable is a primitive type, copy its value, such as Int, float, and so on.

(2) Objects:

If the variable is an instance object, the address reference is copied, that is, the new object shares the instance variable with the original object.

(3) String

If the variable is a String, the reference address is copied, but when modified, it generates a new String from the String pool, leaving the original String object unchanged.

Based on the above rules, it is easy to find the problem. The three of them share the same object. If Zhang SAN modifs the content of the email, Li Si and Wang Wu will also modify it, so the above situation will occur. We can fix this by creating a new object in the clone() method and then making three references to it:

protected Person clone(a) {
        Person person = null;
        try {
            person = (Person) super.clone();
            person.setEmail(new Email(person.getEmail().getObject(),person.getEmail().getContent()));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        
        return person;
    }
Copy the code

​​​​​​​

So: Shallow copy is just a simple copy mechanism provided by Java, not easy to use directly.

There is a problem for the above solution, if there are a large number of objects in our system is generated by copying, if we each class to write a clone () method, and will also need to be deep copy, newly built large object, the project is very big, here we can use serialization to implement a copy of the object.

 

Original blog link:

Blog.csdn.net/jason0539/a…

Blog.csdn.net/jx_87091587…