The prototype model of Java and pattern

Source: Internet
Author: User

In the book "Java and Patterns" of Dr. Shanhong, this describes the prototype (Prototype) pattern:

The prototype mode belongs to the creation mode of the object. By giving a prototype object to indicate the type of all objects created, and then creating more objects of the same type with the method of copying the prototype object. This is the purpose of the model selection.

Structure of the prototype pattern

The prototype pattern requires that an object implement an interface that can "clone" itself, so that a new instance can be created by copying an instance object itself. Thus, by creating a new object from the prototype instance, it is no longer necessary to care about the type of the instance itself, so long as the method of cloning itself is implemented, it is possible to acquire new objects through this method without having to create them through new.

The prototype pattern has two forms: (1) The Simple form, (2) The registration form, these two forms of expression are only the different realization of the prototype pattern.

Prototype mode in simple form

This is a form that involves three roles:

(1) Customer (client) role: The Customer class presents a request to create an object.

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

(3) Specific prototype (concrete Prototype) Role: the object being copied. This role needs to implement the interfaces required by the abstract prototype role.

Source

Abstract prototype role

public interface prototype{    /**     * method of cloning itself     * @return an object cloned from itself * *     public    object Clone ();

Specific prototype roles

public class ConcretePrototype1 implements Prototype {public    Prototype clone () {        //simplest clone, create a new object, The value is no longer copied because there is no attribute        Prototype Prototype = new ConcretePrototype1 ();        return prototype;}    }
public class ConcretePrototype2 implements Prototype {public    Prototype clone () {        //simplest clone, create a new object, The value is no longer copied because there is no attribute        Prototype Prototype = new ConcretePrototype2 ();        return prototype;}    }

Client role

public class Client {    /**     * holds the prototype interface object that needs to be used */    private Prototype Prototype;    /**     * Construction method, incoming the prototype interface object to be used *    /Public Client (Prototype Prototype) {        this.prototype = Prototype;    }    public void operation (Prototype example) {        //object required to create the prototype interface        Prototype Copyprototype = Prototype.clone ();}            }
Prototype mode of the registration form

  

As a second form of prototype mode, it has a prototype manager (Prototypemanager) role that creates objects of a specific prototype class and records each created object.

Source

Abstract prototype role

Public interface prototype{Public    Prototype clone ();    Public String getName ();    public void SetName (String name);

Specific prototype roles

public class ConcretePrototype1 implements Prototype {    private String name;    Public Prototype Clone () {        ConcretePrototype1 Prototype = new ConcretePrototype1 ();        Prototype.setname (this.name);        return prototype;    }    Public String toString () {        return ' now in Prototype1, name = ' + this.name;    }    @Override public    String getName () {        return name;    }    @Override public    void SetName (String name) {        this.name = name;    }}
public class ConcretePrototype2 implements Prototype {    private String name;    Public Prototype Clone () {        ConcretePrototype2 Prototype = new ConcretePrototype2 ();        Prototype.setname (this.name);        return prototype;    }    Public String toString () {        return ' now in Prototype2, name = ' + this.name;    }    @Override public    String getName () {        return name;    }    @Override public    void SetName (String name) {        this.name = name;    }}

The prototype Manager role maintains an aggregation as a registration of all prototype objects, and this role provides the necessary means for the outside world to add new prototype objects and get the registered prototype objects.

public class Prototypemanager {/** * is used to record the corresponding relationship between the prototype number and the prototype instance */private static map<string,prototype> Map    = new Hashmap<string,prototype> (); /** * Privatization construction method, avoid external Create instance */Private Prototypemanager () {}/** * Add or modify a prototype registration in the prototype Manager * @param prototype ID Prototype number * @param prototype prototype instance */public synchronized static void Setprototype (String Prototypeid, Prototy    PE prototype) {Map.put (Prototypeid, prototype); /** * Remove a prototype from the prototype Manager * @param prototypeid prototype number */public synchronized static void Removeprototype (St    Ring Prototypeid) {map.remove (Prototypeid); /** * Gets the prototype instance corresponding to a prototype number * @param prototypeid prototype number * @return prototype instance corresponding to the prototype number * @throws Exception if        The instance of the prototype number does not exist, throws an exception */public synchronized static Prototype Getprototype (String prototypeid) throws exception{        Prototype Prototype = Map.get (Prototypeid); if (prototype = = null) {throw new Exception ("You want to receiveThe prototype has not been registered or has been destroyed ");    } return prototype; }}

Client role

 public class Client {public static void main (String[]args) {try{Prototype p1 = new Concretepro            Totype1 ();            Prototypemanager.setprototype ("P1", p1);            Gets the prototype to create the object Prototype p3 = Prototypemanager.getprototype ("P1"). Clone ();            P3.setname ("Zhang San");            System.out.println ("First Instance:" + p3);            Someone dynamically switched the implementation Prototype P2 = new ConcretePrototype2 ();            Prototypemanager.setprototype ("P1", p2);            Re-acquire the prototype to create the object Prototype P4 = Prototypemanager.getprototype ("P1"). Clone ();            P4.setname ("John Doe");            System.out.println ("second instance:" + P4);            Someone has written off this prototype Prototypemanager.removeprototype ("P1");            Get the prototype again to create the object Prototype P5 = Prototypemanager.getprototype ("P1"). Clone ();            P5.setname ("Harry");        System.out.println ("third instance:" + P5);        }catch (Exception e) {e.printstacktrace (); }    }}
Two forms of comparison

The prototype pattern of simple form and registration form has its merits and shortcomings.

If you need to create a small number of prototype objects and are relatively fixed, you can take the first form. In this case, the reference to the prototype object can be saved by the client itself.

If the number of prototype objects you want to create is not fixed, you can take a second form. In this case, the client does not save a reference to the prototype object, and the task is given to the Administrator object. Before copying a prototype object, the client can see if the Administrator object already has a prototype object that meets the requirements. If so, the object reference can be obtained directly from the Administrator class, and if not, the client needs to replicate the prototype object on its own.

Cloning methods in Java

All classes in Java are inherited from the Java.lang.Object class, and the object class provides a copy of the objects from the protected object Clone () method, which can, of course, displace the method, providing a copy method that satisfies its needs. The basic problem with object replication is that objects typically have references to other objects. When you use the Clone () method of the object class to copy an object, this object's references to other objects are also copied

The Cloneable interface provided by the Java language serves only one function, which is to inform the Java Virtual machine at runtime that it can safely use the Clone () method on this class. You can get a copy of an object by calling this clone () method. Because the object class itself does not implement the Cloneable interface, calling the Clone () method throws a Clonenotsupportedexception exception if the class being considered does not implement the Cloneable interface.

Conditions for cloning to meet

The Clone () method copies a copy of the object and returns it to the caller. The meaning of the so-called "copy" and how the Clone () method is implemented. Generally, the clone () method satisfies the following description:

(1) For any object x, there are: X.clone ()!=x. In other words, a cloned object is not the same object as the original object.

(2) For any object x, there are: X.clone (). GetClass () = = X.getclass (), in other words, the cloned object is the same as the type of the original object.

(3) if the Equals () method of Object x defines its proper words, then x.clone (). Equals (x) should be established.

In the Java language API, all classes that provide the clone () method satisfy these conditions. The Java language designer should also abide by three conditions when designing his own clone () method. In general, the first two of the three conditions above are required, and the third one is optional.

Shallow clones and deep clones

  Whether you are implementing the cloning method yourself or using the cloning method provided by Java, there is a problem of shallow cloning and deep cloning.

    • Superficial cloning

It is only responsible for cloning data passed by value (such as the base data type, string type) without copying the object it refers to, in other words, all references to other objects still point to the original object.

    • Deep cloning

In addition to a shallow clone of the value to be cloned, it is also responsible for cloning the reference type's data. Variables that refer to other objects will point to new objects that have been copied, not those that are already referenced. In other words, a deep clone copies the objects referenced by the object being copied, and this copy of the referenced object is called an indirect copy.

Depth cloning to how many layers, is a difficult to determine the problem. When you decide to copy an object in a deep clone, you must decide whether to take a shallow clone or continue to use deep cloning for objects that are indirectly copied. Therefore, in the case of deep cloning, we need to decide how deep it is to be deep. In addition, in the process of deep cloning, it is very likely that the problem of circular references, must be handled with care.

Using serialization for deep cloning

The process of writing an object into a stream is a serialization (serialization) process, while the process of reading an object from the stream is called a deserialization (deserialization) process. It should be noted that a copy of the object is written to the stream, and the original object still exists inside the JVM.

In the Java language, it is often possible to clone an object in a deep way, so that the object can be implemented serializable interface, then the object (actually a copy of the object) is written into a stream (serialized), and then read back from the stream (deserialized), you can reconstruct the object.

    Public  Object Deepclone () throws IOException, classnotfoundexception{        //Writes the object to the stream        Bytearrayoutputstream BOS = new Bytearrayoutputstream ();        ObjectOutputStream oos = new ObjectOutputStream (BOS);        Oos.writeobject (this);        Read back from the stream        Bytearrayinputstream bis = new Bytearrayinputstream (Bos.tobytearray ());        ObjectInputStream ois = new ObjectInputStream (bis);        return Ois.readobject ();    }

The premise of this is that objects and all objects referenced inside the object are serializable, otherwise, it is necessary to carefully examine whether those objects that are not serializable can be set to transient, thus excluding them from the replication process.

Shallow cloning is obviously easier to implement than deep cloning because all classes in the Java language inherit a clone () method, and the Clone () method does a formal shallow clone.

Some objects, such as thread objects or socket objects, cannot be simply copied or shared. Whether using shallow clones or deep clones, as long as such indirect objects are involved, the indirect object must be set to transient and not copied, or the program will create the equivalent of the same object, right vote used as a copy.

  

Bajau's body spell

What happens if you use a prototype schema in the Java language to Bajau the body's ability to do so? First, the greatest sage, the Thegreatestsage class, plays a customer role. Qi Tianda Saint holds an example of Hozen (Monkey), and Hozen is the Holy Buddha. The Monkey class has a clone () method that inherits from Java.lang.Object, so you can copy a monkey instance by calling the Clone method.

Bajau himself with Thegreatestsage class representative

public class Thegreatestsage {    private Monkey Monkey = new Monkey ();        public void Change () {        //clone the Holy Buddha        Monkey copymonkey = (Monkey) monkey.clone ();        System.out.println ("The Birthday of the Holy Buddha is:" + monkey.getbirthdate ());        System.out.println ("Clone of the Holy of the birthday is:" + monkey.getbirthdate ());        System.out.println ("The Holy Buddha and the clone of the Holy man is the same object" + (monkey = = Copymonkey));        System.out.println ("is the Golden Cudgel held by the Holy Buddha the same object as the Golden Cudgel of the cloned holy man?") "+ (monkey.getstaff () = = Copymonkey.getstaff ()));    }        public static void Main (String[]args) {        Thegreatestsage sage = new Thegreatestsage ();        Sage.change ();    }}

The Holy Buddha is represented by the Monkey class, which plays a specific prototype role:

public class Monkey implements cloneable {//height private int height;    Weight private int weight;    Birthday Private Date birthDate;    Golden Cudgel private Goldringedstaff staff;        /** * constructor */public Monkey () {this.birthdate = new Date ();    This.staff = new Goldringedstaff ();        }/** * Clone method */Public Object clone () {Monkey temp = null;        try {temp = (Monkey) super.clone ();        } catch (Clonenotsupportedexception e) {//TODO auto-generated catch block E.printstacktrace ();        } finally {return temp;    }} 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 Date Getbirthdate () {return birthDate; } public void Setbirthdate (Date birthDate) {THis.birthdate = birthDate;    } public Goldringedstaff Getstaff () {return staff;    } public void Setstaff (Goldringedstaff staff) {this.staff = staff; }    }

The Sage also holds an instance of Golden Cudgel, Golden Cudgel class Goldringedstaff:

public class Goldringedstaff {    private float height = 100.0f;    private float diameter = 10.0f;    /**     * Growth behavior, each call length and radius increase by one times */public    void Grow () {        this.diameter *= 2;        This.height *= 2;    }    /**     * Reduced behavior, length and radius of each call decreased by half */public    void shrink () {        this.diameter/= 2;        This.height/= 2;    }}

When running the Thegreatestsage class, first create the Holy Buddha object, and then the shallow clone of the Holy Buddha object. The information that the program prints at run time is as follows:

It can be seen that, first of all, the copy of the Holy Buddha has the same birthdate as the original sacred objects, and the objects are not equal, which indicates that they are the cloning relationship, and secondly, the copy of the Holy Buddha's Golden Cudgel and the original Holy Buddha held Golden Cudgel as the same object. This shows that the golden cudgel of the two are essentially a root, not a two root.

As mentioned earlier, the Clone () method that inherits from the Java.lang.Object class is a shallow clone. In other words, the Golden Cudgel references held by all avatars of the Holy Grail are all pointing to an object, which is inconsistent with the description in the journey to the monkey. To correct this, you need to consider using deep clones .

For deep cloning , all objects that need to be replicated need to implement the Java.io.Serializable interface.

Source code for Bajau:

public class Thegreatestsage {    private Monkey Monkey = new Monkey ();        public void Change () throws IOException, classnotfoundexception{        Monkey copymonkey = (Monkey) monkey.deepclone ();        System.out.println ("The Birthday of the Holy Buddha is:" + monkey.getbirthdate ());        System.out.println ("Clone of the Holy of the birthday is:" + monkey.getbirthdate ());        System.out.println ("The Holy Buddha and the clone of the Holy man is the same object" + (monkey = = Copymonkey));        System.out.println ("is the Golden Cudgel held by the Holy Buddha the same object as the Golden Cudgel of the cloned holy man?") "+ (monkey.getstaff () = = Copymonkey.getstaff ()));    }        public static void Main (String[]args) throws IOException, classnotfoundexception{        thegreatestsage sage = new Thegreatestsage ();        Sage.change ();    }}

In the Holy Buddha Monkey class, there are two cloning methods, one is clone (), also is a shallow clone, the other is Deepclone (), also known as deep cloning. In the deep cloning method, the venerable object (a copy) is serialized and then deserialized. The deserialized object becomes the result of a deep clone.

  

public class Monkey implements Cloneable,serializable {//height private int height;    Weight private int weight;    Birthday Private Date birthDate;    Golden Cudgel private Goldringedstaff staff;        /** * constructor */public Monkey () {this.birthdate = new Date ();    Staff = new Goldringedstaff ();        }/** * Clone method */Public Object clone () {Monkey temp = null;        try {temp = (Monkey) super.clone ();        } catch (Clonenotsupportedexception e) {//TODO auto-generated catch block E.printstacktrace ();        } finally {return temp; }} public Object Deepclone () throws IOException, classnotfoundexception{//writes the object into the stream bytearrayoutputst        Ream BOS = new Bytearrayoutputstream ();        ObjectOutputStream oos = new ObjectOutputStream (BOS);        Oos.writeobject (this);        Read back from the stream bytearrayinputstream bis = new Bytearrayinputstream (Bos.tobytearray ()); ObjectinputstreaM ois = new ObjectInputStream (bis);    return Ois.readobject ();    } 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 Date Getbirthdate () {return birthDate;    } public void Setbirthdate (Date birthDate) {this.birthdate = birthDate;    } public Goldringedstaff Getstaff () {return staff;    } public void Setstaff (Goldringedstaff staff) {this.staff = staff; }    }

As you can see, the Holy Buddha holds an example of a golden Cudgel (Goldringedstaff). In the holy Copy, this golden Cudgel instance is a copy of the Golden Cudgel object held by the original Holy Buddha object. When the sacred object is serialized and deserialized, the Golden Cudgel object It holds is also serialized and deserialized, which makes the Golden Cudgel object held by the Golden Cudgel and the original sacred object of the copy of the Holy Buddha two separate objects.

public class Goldringedstaff implements serializable{    private float height = 100.0f;    private float diameter = 10.0f;    /**     * Growth behavior, each call length and radius increase by one times */public    void Grow () {        this.diameter *= 2;        This.height *= 2;    }    /**     * Reduced behavior, length and radius of each call decreased by half */public    void shrink () {        this.diameter/= 2;        This.height/= 2;    }}

Operation Result:

It can be seen from the running results that the Golden cudgel of the sage and the golden cudgel of his body outside are different objects. This is due to the use of deep clones, which also copy the objects referenced by the Holy Buddha, including Golden Cudgel.

  

Advantages of Prototype mode

Prototype mode allows you to dynamically change the specific implementation type at run time. Prototype mode can be used during the run, by the customer to register the implementation type conforming to the prototype interface, you can also dynamically change the specific implementation type, it seems that the interface has not changed, but actually running is already another class instance. Because cloning a prototype is analogous to instantiating a class.

Disadvantages of prototype mode

The main disadvantage of prototype mode is that each class must be equipped with a clone method. Having a cloning method requires a holistic view of the functionality of the class, which is not difficult for new classes, and not necessarily easy for existing classes, especially when a class references an indirect object that does not support serialization, or when a reference contains a looping structure.

The prototype model of Java and pattern

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.