Design Patterns--Prototype Patterns

Posted by huppsi on Tue, 21 Jan 2020 03:37:10 +0100

Prototype mode is used to create duplicate objects while maintaining performance, creating new instances by copying existing instances without knowing class information.

Unlike constructing new objects by instantiating a class, a prototype pattern generates new objects by copying an existing object.

So how do you implement the prototype pattern in java?The essence of a prototype pattern is a clone, which copies an identical object.

The implementation prototype pattern in java can be divided into two types: shallow copy and deep copy.

The shallow copy implementation prototype pattern implements a cloning interface, which is the cloning used to create the current object.Here is the code to make a shallow copy.

First, define a class that implements the clone() method within the Cloneable interface.

public class Person implements Cloneable {

    String name;
    int age;
    int[] a;
    @Override
    public Object clone() throws CloneNotSupportedException{
        Object obj = super.clone();
        return obj;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public int[] getA() {
        return a;
    }

    public void setA(int[] a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a=" + Arrays.toString(a) +
                '}';
    }
}
public static void main(String[] args) throws CloneNotSupportedException{
        Person p = new Person();
        p.setAge(10);
        p.setName("Jack");
        p.setA(new int[]{1});
        System.out.println("Precloning p Value of:"+p);
        Person p2 = (Person)p.clone();
        System.out.println("Unmodified before cloning p2 Value of:"+p2);
        p2.setAge(11);
        p2.setName("Tom");
        int[] a = p2.getA();
        a[0] = 2;
        p2.setA(a);
        System.out.println("Modify after cloning p2 Value of, p2 The value of:"+p2);
        System.out.println("Modify after cloning p2 Value of, p The value of:"+p);
    }

Value of pre-clone p: Person{name='Jack', age=10, a=[1]}
The value of p2 was not modified before cloning: Person{name='Jack', age=10, a=[1]}
Modify p 2 values after cloning: Person{name='Tom', age=11, a=[2]}
Modify the value of p 2 after cloning, the value of p is Person{name='Jack', age=10, a=[2]}

From the above code, we find that modifying the values of String and int types of p2 cloned from P does not change the values of the corresponding types of p, but when modifying the values of reference type int[], the corresponding types of P also change, which means that for basic types, a shallow copy copies the values of member variables of value type, and for quotationCopy references with variables of type, not with referenced objects.String is a special type whose data is placed in a constant pool. The modification to p2 is to point the reference to its String type from "Jack" to "Tom", while the String type of P still points to "Jack" and has not changed.

So, there are many times when I don't want changes to the copied object to affect the original object, and then we need to make a deep copy.

Deep copy: Make a value copy of a member variable of a value type, copy a reference to a variable of a reference type, and copy the referenced object.Simply put, deep copies are individual copies of attributes that simply copy references without copying objects.

First method: Copy the object of the reference type again individually

public class Person implements Cloneable {

    String name;
    int age;
    int[] a;
    @Override
    public Person clone() throws CloneNotSupportedException{

        Person person = (Person)super.clone();
        person.a = this.a.clone();
        return person;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public int[] getA() {
        return a;
    }

    public void setA(int[] a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a=" + Arrays.toString(a) +
                '}';
    }
}

A deep copy can be made by directly copying a reference to the int[] array type in the clone() method in a separate copy.

The second method is to serialize an object into a byte sequence using a javaIO stream. By default, the entire object graph of the object is serialized, and then the deep copy is perfectly achieved by deserializing.

public static void main(String[] args) throws Exception{
        Person person = new Person();
        person.setAge(10);
        person.setName("Jack");
        person.setA(new int[]{1});

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //ObjectOutputStream Object Output Stream
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(person);
        oos.flush();
        //ObjectOutputStream Object Input Stream
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        Person person2 = (Person)ois.readObject();
        System.out.println("Modify after deep copy person2 Value of:"+person2);
        person2.setName("Tom");
        person2.setAge(12);
        int[] a = person2.getA();
        a[0] = 3;
        person2.setA(a);
        System.out.println("Modify after deep copy person2 Value of:"+person2);
        System.out.println("Modify after deep copy person2 Value of, person The value is:"+person);
    }
Modify person2 values after deep copy: Person{name='Jack', age=10, a=[1]}
Modify person2 values after deep copy: Person{name='Tom', age=12, a=[3]}
Modify person 2 values after deep copy, person values are Person{name='Jack', age=10, a=[1]}

We see that modifying person2 values does not affect person values after deep copy.It is important to note that if an attribute is modified with a transient keyword, it will not be serialized.

11 original articles published. 0% praised. 33% visited
Private letter follow

Topics: Java Attribute