Original (Prototype) mode

  Prototype Mode: Specifies the type of object prototype created instance, and create new objects by copying the prototype objects.

  In fact, another prototype model is to create a copy of an object from an object, and does not need to know details of any created. (The most commonly used is based on the flow of deep copy)

 The original model mode

   Java language itself supports the original prototype model. All JavaBean inherit from Java.lang.Object, and Object class provides a clone method, you can copy a JavaBean object. But the JavaBean must implement an interface that represents Cloneable, indicating that this JavaBean support replication. If an object does not implement this interface and call the clone () method, Java compiler will throw a CloneNotSupportedException.

Reference variables, objects, and objects

  The object is an instance of the class. Normally, when a class is instantiated, all members of this family, including the variables and methods, are copied to belong to a new instance of this type of data fetch. such as:

User user = new User();

The above statement made the following things:

(1) User creates a type of variable called user

(2) the establishment of a User object class

(3) user refers to the variable object.

The above can be divided into the following two steps:

        User user;
        user = new User();

  The first line creates a variable called user, you may refer to the User class object. But at the end of the first row above does not refer to it, but in the second row really refers to such an object.

  The second line creates an object. When the object is just to create an unnamed object and then the object is only the name of a user.

  It is also possible to create an object after being there is no name, forever remain nameless state.

        User user = new User();
        user.setBirthDay(new Date());

   As above, we know that passing parameters are passed by reference, so just pass on the address. setBirthDay accept arguments do not care it receives object has no name.

   Therefore, to create objects with their references are independent

Cloning conditions met

  clone () method to copy a target and return to the caller. The so-called "copy" meaning clone () method is how to achieve. Generally, clone () method satisfies the following description:

  (1) for any object x, are: x.clone () = x!. In other words, clone the original object is not the same object.

  (2) for any object x, are:. X.clone () getClass () == x.getClass (), in other words, the type of the original clone and the same object.

  (3) If the object x equals () method defined in its proper, then x.clone (). Equals (x) should be established.

  In the JAVA language API, it provides a clone of all () method, which satisfy the above conditions. JAVA language designers when designing your own clone () method, should also comply with the three conditions. In general, the above three conditions are required for the first two, while the third is optional.

Raw mode structure:

  Prototype model has two forms: (1) simple form; (2) the registration form.

(1) simple form:

Three roles:

  (1) client (Client) Role: client request to create an object of class.

  (2) the abstract prototype (Prototype) Role: This is an abstract role, usually implemented by a Java interface or Java abstract class. This role gives all the necessary specific prototype class interface.

  (3) specific prototype (Concrete Prototype) roles: the object is copied. This role needs to implement the interface abstract prototype role requires.

as follows:

package cn.qlq.prototype;

public interface Prototype {

    Prototype clone();
}
package cn.qlq.prototype;

public class ConcretePrototype1 implements Prototype {

    public the Prototype clone () {
         // do not copy the value of the property is no longer 
        the Prototype = the prototype new new ConcretePrototype1 ();

        return prototype;
    }

}
package cn.qlq.prototype;

public class ConcretePrototype2 implements Prototype {

    public the Prototype clone () {
         // do not copy the value of the property is no longer 
        the Prototype = the prototype new new ConcretePrototype2 ();
         return the prototype;
    }

}

 

Client code:

package cn.qlq.prototype;

public  class Customer {

    private Prototype prototype;

    public Client(Prototype prototype) {
        this.prototype = prototype;
    }

    public void operation(Prototype example) {
        Prototype copyPrototype = prototype.clone();
    }

}

 

(2) Registration form

   As a second form of the prototype model, which is more than the simple form of a prototype manager (PrototypeManager) role, the role of the role is: to create objects specific prototype class, and record every object is created.

   Prototype Manager role to maintain a set of registration as a prototype for all objects, this role provides the necessary methods for adding new prototype object outside and made the prototype object has been registered before.

package cn.qlq.prototype;

import java.util.HashMap;
import java.util.Map;

public  class PrototypeManager {

    private static Map<String, Prototype> prototypes = new HashMap<String, Prototype>();

    private PrototypeManager() {
    }

    public synchronized static void setPrototype(String prototypeId, Prototype prototype) {
        prototypes.put(prototypeId, prototype);
    }

    public synchronized static void removePrototype(String prototypeId) {
        prototypes.remove(prototypeId);
    }

    public synchronized static Prototype getPrototype(String prototypeId) throws Exception {
        Prototype prototype = prototypes.get(prototypeId);
        if (prototype == null) {
            throw new Exception("不存在");
        }

        return prototype;
    }
}

 

Test code:

package cn.qlq.prototype;

public  class Customer {

    public static void main(String[] args) throws Exception {
        Prototype p1 = new ConcretePrototype1();
        PrototypeManager.setPrototype ( "p1" , p1);
         // get the prototype to create an object and a copy of 
        Prototype p3 = PrototypeManager.getPrototype ( "p1" ) .clone ();
        System.out.println(p1 == p3);
    }

}

Comparison of two forms:

  If the number of objects you need to create a prototype and less fixed, it can take the first form is simple form of the original model mode. In this case, the prototype object referenced by the client's own preservation.

  If the number of the prototype object to be created is not fixed, using the registration form. Save the original object referenced by the execution manager role. Before copying a prototype object, the client can see if the administrator object already has a prototype object to meet the requirements, if there is a direct return, if the client does not need to copy the prototype object itself.

 

Shallow copy and deep copy:

Shallow copy
  only responsible for cloning according to data (such as basic data types, String type) passed by value, rather than copy the object it refers to, in other words, all the references to other objects are still pointing to the original object.

Deep copy
  in addition to the value of the shallow clone to clone, clone reference is also responsible for the data type. Variables that reference other objects will point to the new object is copied, rather than the original objects that are referenced. In other words, the depth of the object Object clone to be copied are copied referenced again, and this is a reference to the copy of the object is called indirect reproduction.

  To drill down to a depth of cloned how many layers, is a question not easy to determine. In order to determine the depth of cloning a way to copy an object, you must decide to take a shallow clone of an object or indirect reproduction continue to use the depth of cloning. Therefore, when taking a deep clone, you need to decide how deep is considered deep. In addition, during the depth of cloning, it is likely there will be problems with circular references, it must be handled with care.

Realization of a deep clone using the serial :( important )

  The objects written to the stream in a process called serialization in Java, also known as "frozen" or "marinade"; and the object is read out from the stream in a parallel process is called "thaw" or "fresh back "process. It should be noted that wrote the stream is a copy of the object, and the original object still exists inside the JVM, so "marinade" is just a copy of the object.

  In the Java language in a deep clone an object, the object can often be achieved to make the Serializable interface, then the object (actually only copy of the object) is written in a stream (serialization), and then read back from the stream (deserialize) , you can reconstruct the object.

The following code:

     public static <T> T cloneObj(T obj) {
            T retVal = null;

            the try {
                 // the object in the stream is written 
                ByteArrayOutputStream BAOS = new new ByteArrayOutputStream ();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject (obj);

                // read from the stream objects 
                A ByteArrayInputStream Bais = new new A ByteArrayInputStream (baos.toByteArray ());
                ObjectInputStream ois = new ObjectInputStream(bais);

                retVal = (T) ois.readObject();
            } catch (Exception e) {
                e.printStackTrace ();
            }

            return retVal;
        }

  Premise of this is that all the objects and internal object references to objects are serializable, otherwise, you need to closely examine the possibility of non-serialized object is set to transient, so it will be excluded from the replication process.

  Obviously deeper than the shallow copy copy easier to implement, because all classes of the Java language will inherit a clone () method, and this clone () method does is shallow copy.

  Some objects, such as thread (Thread) Socket object or objects that can not simply be copied or shared. Whether you use a shallow copy or a deep copy, as long as relates to the indirect object, indirect object must be set to transient and not to copy; or by the program itself create quite the same kind of object the time being as a copy to use.

 

Test code as follows:

  User is the root object, which have internal reference class implements Serializable interfaces, user name attribute is not modified by the sequence of transient keyword.

package cn.qlq.prototype;

import java.io.Serializable;

public class User implements Serializable {

    private Address address;

    private int id;

    private transient String name;
    private String sex;
    private String job;
    private String health;
    private String BMI;
    private int height;
    private int weight;

    public User() {
        super();
    }

    public User(Address address, int id, String name, String sex, String job, String health, String bMI, int height,
            int weight) {
        super();
        this.address = address;
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.job = job;
        this.health = health;
        BMI = bMI;
        this.height = height;
        this.weight = weight;
    }

    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 getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public String getHealth() {
        return health;
    }

    public void setHealth(String health) {
        this.health = health;
    }

    public String getBMI() {
        return BMI;
    }

    public void setBMI(String bMI) {
        BMI = BMI;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User [address=" + address + ", id=" + id + ", name=" + name + ", sex=" + sex + ", job=" + job
                + ", health=" + health + ", BMI=" + BMI + ", height=" + height + ", weight=" + weight + "]";
    }

}

class Address implements Serializable {

    private String province;

    private String country;

    public Address(String province, String country) {
        super();
        this.province = province;
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Override
    public String toString() {
        return "Address [province=" + province + ", country=" + country + "]";
    }

}
    public static void main(String[] args) throws Exception {
        User user = new User();
        user.setName ( "Joe Smith" );
        user.setBMI("BMI");
        user.setHealth ( "Health" );
        user.setHeight(50);
        user.setId(1);
        Address address = new Address("山西", "cn");
        user.setAddress(address);

        // clone object and modify the properties after printing 
        the User cloneedUser = cloneObj (User);
        cloneedUser.getAddress().setCountry("北京");
        System.out.println(cloneedUser);

        System.out.println("========");
        System.out.println(user);
    }

Results: (name attribute is not replicate, and its address is deep copy)

User [address = Address [province = Shanxi, country = Beijing], id = 1, name = null, sex = null, job = null, health = health, BMI = BMI, height = 50, weight = 0]
=== =====
the User [address the address = [= Shanxi Province, country = cn], id = 1, name = Joe Smith, sex = null, job = null , health = health, BMI = BMI, height = 50 , weight = 0]

 

The advantages of prototype models

  Prototype mode allows the realization of particular types of dynamically changing at runtime. Prototype mode during operation, by the customer to register in line with the implementation type prototype interface, can also dynamically change the specific implementation types, it seems there is no change in the interface, but in fact is already running another instance of the class. Because clone is similar to a prototype of a class instance.

Disadvantage of prototype models

  The main disadvantage of the prototype model is that each class must be equipped with a cloning method. With cloning method requires functional classes take into consideration, for this new class is not difficult, but to have some classes may not be very easy, especially when a class does not support the reference sequence of the indirect object, or a reference when containing cyclic structure.

 

Applicable scene: 

  Suppose a system product class is dynamically loaded, and the product has a certain hierarchical structure. This time if you use the factory model, then you have to have a certain factory model structure. The product class hierarchy changes, the factory class hierarchy must change with it. This may become a regular product structure systems using factory pattern is not convenient.

  This time you can use the prototype model, to each product fitted with a cloning method (most of the time only to the root class assembling cloning product category).

 

to sum up:

  Most is a deep copy of this mode of use, the project is useless to this pattern.

 

Guess you like

Origin www.cnblogs.com/qlqwjy/p/11024319.html