Java Design Patterns - Prototype Patterns

Java Design Patterns - Prototype Patterns

Object-oriented programming, which deals with objects all the time, can sometimes be cumbersome to get an instantiated object.For example, one needs to access a large number of datasheets associated with the database to get an instance, such as the object's attributes are very many, getting the object through the constructor needs to initialize many objects, which is cumbersome and wastes memory.Scenes like this require prototype mode to solve the problem.

Prototype mode: It is simpler to get the same or similar object instances.It can be understood as replication, cloning.

Here are two concepts

Shallow cloning: The cloned object instances are identical, and the object's attributes point to the same address value if they refer to a data type.Whether you modify the original object or the cloned object, as long as the reference data type is modified, both objects are modified simultaneously because they share the same address value.

Deep cloning: The cloned object instances are identical, but their reference properties are also cloned. The two objects are identical, but have no relationship.Modify one object without affecting the other.

Requirements: To clone the object of electronic invoice, electronic invoice has object attributes such as invoice head, invoice number, name, unit, company, color, supervisory seal, company seal, validity, etc.Making an invoice is still a hassle, so use the prototype mode to quickly copy the invoice objects and efficiently complete the requirements.

Provides a prototype interface for prototype management and business expansion.

/**
 * @description: Prototype mode prototype interface
 * @author: lmc
 * @create: 2019-05-29 20:32
 **/
public interface Prototype {

    /**
     * @description: Obtaining Shallow Clone Objects
     * @return java.lang.Object
     * @date 2019/5/29 20:35
     * @author lmc
     */
    Prototype getShallowCloneInstance() throws CloneNotSupportedException;
    /**
     * @description: Getting Deep Clone Objects
     * @return com.lmc.gp12380.pattern.prototype.Prototype
     * @date 2019/5/30 21:15
     * @author lmc
     */
    Prototype getDeepCloneInstance(Prototype prototype);

}

Providing a tool class for deep cloning using serialization; of course, all referenced object classes that need to be cloned can also be shallow cloned according to business requirements, which is also a deep cloned object, but this method is cumbersome and easy to ignore that objects are not shallow cloned.

/**
 * @description: Prototype Tool Class
 * @author: lmc
 * @create: 2019-05-30 21:27
 **/

public class PrototypeUtil {
    /**
     * @description: Getting a deeply cloned object through serialization
     * @param prototype
     * @return com.lmc.gp12380.pattern.prototype.Prototype
     * @date 2019/5/30 21:34
     * @author lmc
     */
    public static Prototype getSerializInstance(Prototype prototype){
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(prototype);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            Prototype copy = (Prototype)ois.readObject();
            bos.flush();
            bos.close();
            ois.close();
            return copy;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

Electronic Invoice Seal Picture Class

/**
 * @description: Electronic Invoice Seal Picture
 * @author: lmc
 * @create: 2019-05-29 21:21
 **/

public class Image implements Serializable,Prototype,Cloneable {
    /**
     * colour
     */
    private String color="red";
    /**
     * height
     */
    private Integer height=10;
    /**
     * width
     */
    private Integer width=8;

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public Integer getHeight() {
        return height;
    }

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

    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    @Override
    public String toString() {
        return "Image{" +
                "color='" + color + '\'' +
                ", height=" + height +
                ", width=" + width +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public Prototype getShallowCloneInstance() throws CloneNotSupportedException {
        return (Prototype) clone();
    }

    public Prototype getDeepCloneInstance(Prototype prototype) {
        return PrototypeUtil.getSerializInstance(prototype);
    }
}
/**
 * @description: Electronic Seal
 * @author: lmc
 * @create: 2019-05-29 21:19
 **/
public class Seal implements Serializable,Cloneable,Prototype {
    /**
     * Seal Name
     */
    private String name;
    /**
     * Known Pictures
     */
    private Image image;

    public String getName() {
        return name;
    }

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

    public Image getImage() {
        return image;
    }

    public void setImage(Image image) {
        this.image = image;
    }

    @Override
    public String toString() {
        return "Seal{" +
                "name='" + name + '\'' +
                ", image=" + image +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public Prototype getShallowCloneInstance() throws CloneNotSupportedException {
        return (Prototype) clone();
    }

    public Prototype getDeepCloneInstance(Prototype prototype) {
        return PrototypeUtil.getSerializInstance(prototype);
    }
}
/**
 * @description: E-Invoice
 * @author: lmc
 * @create: 2019-05-29 20:36
 **/
public class Invoice implements Cloneable,Serializable,Prototype {

    /**
     * Ticket Head
     */
    private String ticketHeader;
    /**
     * Ticket Number
     */
    private int ticketNo;
    /**
     * Invoice Joint Name
     */
    private String name;
    /**
     * Invoice couplet color
     */
    private String color;
    /**
     * Invoice Associates
     */
    private String company;
    /**
     * Company Seal
     */
    private Seal companySeal;
    /**
     * Supervisory Seal
     */
    private Seal supervisedSeal;
    /**
     * Is it valid
     */
    private Boolean effective;

    public String getTicketHeader() {
        return ticketHeader;
    }

    public void setTicketHeader(String ticketHeader) {
        this.ticketHeader = ticketHeader;
    }

    public int getTicketNo() {
        return ticketNo;
    }

    public void setTicketNo(int ticketNo) {
        this.ticketNo = ticketNo;
    }

    public String getName() {
        return name;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public Seal getCompanySeal() {
        return companySeal;
    }

    public void setCompanySeal(Seal companySeal) {
        this.companySeal = companySeal;
    }

    public Seal getSupervisedSeal() {
        return supervisedSeal;
    }

    public void setSupervisedSeal(Seal supervisedSeal) {
        this.supervisedSeal = supervisedSeal;
    }

    public Boolean getEffective() {
        return effective;
    }

    public void setEffective(Boolean effective) {
        this.effective = effective;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Invoice{" +
                "ticketHeader='" + ticketHeader + '\'' +
                ", ticketNo=" + ticketNo +
                ", name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", company='" + company + '\'' +
                ", companySeal=" + companySeal +
                ", supervisedSeal=" + supervisedSeal +
                ", effective=" + effective +
                '}';
    }

    public Prototype getShallowCloneInstance() throws CloneNotSupportedException {
        return (Prototype)clone();
    }

    public Prototype getDeepCloneInstance(Prototype prototype) {
        return PrototypeUtil.getSerializInstance(prototype);
    }
}

The Invoice class of electronic invoice contains Seal class of seals; Seal seal class contains Image class; Invoice, Seal, Image are all implemented

Prototype, Cloneable, Serializable interfaces.

clone(): is a method of the Object class, which can quickly copy an object, belongs to shallow cloning, and does not copy the attributes of the referenced object.

Cloneable interface: Implement this interface to invoke the clone() method.

Serializable interface: A class implements this interface so that its objects can be serialized and deserialized.

Test Code

/**
 * @description: Prototype mode testing
 * @author: lmc
 * @create: 2019-05-29 21:46
 **/
public class PrototypeClientTest {

    public static void main(String[] args) throws CloneNotSupportedException {

        Invoice invoice=new Invoice();
        invoice.setColor("bule");
        invoice.setTicketNo(1);
        invoice.setEffective(false);
        invoice.setCompanySeal(new Seal());
        //Testing shallow clones
        //Invoice invoiceClone = (Invoice) invoice.getShallowCloneInstance();
        //
        Invoice invoiceClone = (Invoice) invoice.getDeepCloneInstance(invoice);
        /**
         * Verify that the objects are the same.
         */
        System.out.println("invoice_"+invoice.hashCode());
        System.out.println("Clone_invoice_"+invoiceClone.hashCode());
        System.out.println("Validate Object_"+(invoice==invoiceClone));
        /**
         * Verify that the basic data types are equal.
         */
        System.out.println("getTicketNo_"+invoice.getTicketNo());
        System.out.println("Clone_getTicketNo_"+invoiceClone.getTicketNo());
        System.out.println("Validate basic data types_"+(invoice.getTicketNo()==invoiceClone.getTicketNo()));
        /**
         * Verify that reference data types are equal
         */
        System.out.println("getColor_"+invoice.getColor().hashCode());
        System.out.println("Clone_getColor_"+invoiceClone.getColor().hashCode());
        System.out.println("Validate Reference Data Types_"+(invoiceClone.getColor() == invoice.getColor()));

        System.out.println("getCompanySeal_"+invoice.getCompanySeal().hashCode());
        System.out.println("Clone_getCompanySeal_"+invoiceClone.getCompanySeal().hashCode());
        System.out.println("Validate Reference Data Types_"+(invoice.getCompanySeal() == invoiceClone.getCompanySeal()));
       	  System.out.println("____________________________________________________________");
        /**
         * Verify basic data type modifications
         */
        invoice.setTicketNo(2);
        System.out.println("Verify basic data type modifications"+invoice);
        System.out.println("Verify basic data type modifications"+invoiceClone);
        /**
         * Validate Basic Data Type Guaranteed Packaging Class
         */
        invoice.setEffective(true);
        System.out.println("Validate basic data type wrapper classes"+invoice);
        System.out.println("Validate basic data type wrapper classes"+invoiceClone);
        /**
         * Validate Reference Data Types
         */
        invoice.getCompanySeal().setName("Validate Reference Data Types");
        System.out.println("Validate Reference Data Types"+invoice);
        System.out.println("Validate Reference Data Types"+invoiceClone);
    }
}

Test Deep Clone Results

The deep cloned objects and the original objects are two separate objects. Although their contents are the same, they have no relationship.

Testing shallow clone results

Shallow cloned objects and original objects are also two objects, but their reference property objects share the same object.The company seal of the cloned object was modified as well as the company seal of the cloned object.The basic data type and the packaging type of the basic data type are not shared.

Shallow Clone Model Diagram

For shallow cloning: the basic data type in stack memory stores values, and the reference data type stores reference address values.Shallow cloning copies all basic data types, and reference data types copy reference address values.Note: For basic data type wrapper type, String type, and basic data type, assigning an operation to it is equivalent to creating an object from scratch. The previous object or value becomes unreachable and can only be recycled by the garbage collector.Although the basic data type's packaging type and String are both reference data types, it is not possible to prove that they share the same address value (hopefully the God will be confused).

Deep Clone Model Diagram

For deep cloning: deep cloning copies all data, whether it is a basic data type or a reference data type.There is no relationship between the two objects, and they are completely independent, although they look the same.

Summary: All programs serve the business. According to business requirements, if the prototype mode is easier and more reasonable to obtain objects, then the prototype mode should be used. If using the prototype mode instead makes object acquisition more complex, the complexity of the program increases and readability decreases.Design patterns should not be enforced.

Tags: Java Programming Database

Posted on Wed, 08 Apr 2020 21:12:22 -0700 by w4designs