© Vaskaran Sarcar 2019
Vaskaran SarcarJava Design Patternshttps://doi.org/10.1007/978-1-4842-4078-6_2

2. Prototype Pattern

Vaskaran Sarcar1 
(1)
Bangalore, Karnataka, India
 

This chapter covers the prototype pattern.

GoF Definition

Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.

Concept

In general, creating a new instance from scratch is a costly operation. Using the prototype pattern, you can create new instances by copying or cloning an instance of an existing one. This approach saves both time and money in creating a new instance from scratch.

Real-World Example

Suppose we have a master copy of a valuable document. We need to incorporate some changes to it to see the effect of the change. In such a case, we can make a photocopy of the original document and edit the changes.

Consider another example. Suppose a group of people decide to celebrate the birthday of their friend Ron. They go to a bakery and buy a cake. To make it special, they request the seller to write, “Happy Birthday Ron” on the cake. From the seller’s point of view, he is not making any new model. He already defined the model and produces many cakes (which all look the same) every day by following the same process, and finally makes each special with some small changes.

Computer-World Example

Let’s assume that you have an application that is very stable. In the future, you may want to update the application with some small modifications. So, you start with a copy of your original application, make changes, and analyze further. Surely, to save your time and money, you do not want to start from scratch.

Note

Consider the Object.clone() method as an example of a prototype.

Illustration

Figure 2-1 illustrates a simple prototype structure.
../images/395506_2_En_2_Chapter/395506_2_En_2_Fig1_HTML.jpg
Figure 2-1

A sample prototype structure

Here, BasicCar is a basic prototype. Nano and Ford are the concrete prototypes that have implemented the clone() method defined in BasicCar. In this example, we have created a BasicCar class with a default price (in Indian currency). Later, we modify the price per model. PrototypePatternExample.java is the client in this implementation.

Class Diagram

Figure 2-2 shows a class diagram of the prototype pattern.
../images/395506_2_En_2_Chapter/395506_2_En_2_Fig2_HTML.jpg
Figure 2-2

Class diagram

Package Explorer View

Figure 2-3 shows the high-level structure of the program.
../images/395506_2_En_2_Chapter/395506_2_En_2_Fig3_HTML.jpg
Figure 2-3

Package Explorer view

Implementation

Here’s the implementation.
//BasicCar.java
package jdp2e.prototype.demo;
import java.util.Random;
public abstract class BasicCar implements Cloneable
{
    public String modelName;
    public int basePrice,onRoadPrice;
    public String getModelname() {
        return modelName;
    }
    public void setModelname(String modelname) {
        this.modelName = modelname;
    }
    public static int setAdditionalPrice()
    {
        int price = 0;
        Random r = new Random();
        //We will get an integer value in the range 0 to 100000
        int p = r.nextInt(100000);
        price = p;
        return price;
    }
    public BasicCar clone() throws CloneNotSupportedException
    {
        return  (BasicCar)super.clone();
    }
}
//Nano.java
package jdp2e.prototype.demo;
class Nano extends BasicCar
{
    //A base price for Nano
    public int basePrice=100000;
    public Nano(String m)
    {
        modelName = m;
    }
    @Override
    public BasicCar clone() throws CloneNotSupportedException
    {
         return (Nano)super.clone();
         //return this.clone();
    }
}
//Ford.java
package jdp2e.prototype.demo;
class Ford extends BasicCar
{
    //A base price for Ford
    public int basePrice=100000;
    public Ford(String m)
    {
        modelName = m;
    }
    @Override
    public BasicCar clone() throws CloneNotSupportedException
    {
        return (Ford)super.clone();
    }
}
//Client
// PrototypePatternExample.java
package jdp2e.prototype.demo;
public class PrototypePatternExample
{
    public static void main(String[] args) throws CloneNotSupportedException
    {
        System.out.println("***Prototype Pattern Demo*** ");
        BasicCar nano = new Nano("Green Nano") ;
        nano.basePrice=100000;
        BasicCar ford = new Ford("Ford Yellow");
        ford.basePrice=500000;
        BasicCar bc1;
        //Nano
        bc1 =nano.clone();
        //Price will be more than 100000 for sure
        bc1.onRoadPrice = nano.basePrice+BasicCar.setAdditionalPrice();
        System.out.println("Car is: "+ bc1.modelName+" and it's price is Rs."+bc1.onRoadPrice);
        //Ford
        bc1 =ford.clone();
        //Price will be more than 500000 for sure
        bc1.onRoadPrice = ford.basePrice+BasicCar.setAdditionalPrice();
        System.out.println("Car is: "+ bc1.modelName+" and it's price is Rs."+bc1.onRoadPrice);
    }
}

Output

Here’s the output.
***Prototype Pattern Demo***
Car is: Green Nano and it's price is Rs.123806
Car is: Ford Yellow and it's price is Rs.595460

Note

You can see a different price in your system because we are generating a random price in the setAdditionalPrice() method inside the BasicCar class. But I have assured that the price of the Ford will be greater than the Nano.

Q&A Session

  1. 1.
    What are the advantages of using prototype design patterns?
    • It is useful when creating an instance of a class is a complicated (or boring) process. Instead, you can focus on other key activities.

    • You can include or discard products at runtime.

    • You can create new instances at a cheaper cost.

     
  2. 2.
    What are the challenges associated with using prototype design patterns?
    • Each subclass needs to implement the cloning or copying mechanism.

    • Sometimes creating a copy from an existing instance is not simple. For example, implementing a cloning mechanism can be challenging if the objects under consideration do not support copying/cloning or if there are circular references. For example, in Java, a class with the clone() method needs to implement the Cloneable marker interface; otherwise, it will throw a CloneNotSupportedException.

    • In this example, I have used the clone() method that performs a shallow copy in Java. Following the convention, I obtained the returned object by calling super.clone().(If you want to learn more about this, put your cursor on the eclipse editor and go through the instructions). If you need a deep copy for your application, that can be expensive.

     
  3. 3.

    Can you please elaborate the difference between a shallow copy and a deep copy?

    A shallow copy creates a new object and then copies various field values from the original object to the new object. So, it is also known as a field-by-field copy . If the original object contains any references to other objects as fields, then the references of those objects are copied into the new object, (i.e., you do not create the copies of those objects).

    Let’s try to understand the mechanism with a simple diagram. Suppose we have an object, X1, and it has a reference to another object, Y1. Further assume that object Y1 has a reference to object Z1.
    ../images/395506_2_En_2_Chapter/395506_2_En_2_Fig4_HTML.jpg
    Figure 2-4

    Before shallow copy of the reference/s

     
Now, with the shallow copy of X1, a new object, X2, is created; it also has a reference to Y1.
../images/395506_2_En_2_Chapter/395506_2_En_2_Fig5_HTML.jpg
Figure 2-5

After the shallow copy of the reference

You have already seen the use of the clone() method in our implementation. It performs a shallow copy.

For a deep copy of X1, a new object, X3, is created. X3 has a reference to new object Y3, which is actually a copy of Y1. Also, Y3, in turn, has a reference to another new object, Z3, which is a copy of Z1.
../images/395506_2_En_2_Chapter/395506_2_En_2_Fig6_HTML.jpg
Figure 2-6

After the deep copy of the reference

In a deep copy, the new object is totally separated from the original one. Any changes made in one object should not be reflected on the other one. To create a deep copy in Java, you may need to override the clone() method and then proceed. Also, a deep copy is expensive because you need to create additional objects. A complete implementation of deep copy is presented in the “Q&A Session” of Memento Pattern (Chapter 19) in this book.
  1. 4.

    When do you choose a shallow copy over a deep copy (and vice versa)?

    A shallow copy is faster and less expensive. It is always better if your target object has the primitive fields only.

    A deep copy is expensive and slow. But it is useful if your target object contains many fields that have references to other objects.

     
  2. 5.

    When I copy an object in Java, I need to use the clone() method. Is this understanding correct?

    No. There are alternatives available, and one of them is to use the serialization mechanism. But you can always define your own copy constructor and use it.

     
  3. 6.

    Can you give a simple example that demonstrates a user-defined copy constructor?

    Java does not support a default copy constructor. You may need to write your own. Consider the following program, which demonstrates such a usage.

     

Demonstration

Here’s the demonstration.
package jdp2e.prototype.questions_answers;
class Student
{
    int rollNo;
    String name;
    //Instance Constructor
    public Student(int rollNo, String name)
    {
        this.rollNo = rollNo;
        this.name = name;
    }
    //Copy Constructor
    public Student( Student student)
    {
        this.name = student.name;
        this.rollNo = student.rollNo;
    }
    public void displayDetails()
    {
        System.out.println(" Student name: " + name + ",Roll no: "+rollNo);
    }
}
class UserDefinedCopyConstructorExample {
    public static void main(String[] args) {
        System.out.println("***User defined copy constructor example in Java*** ");
        Student student1 = new Student(1, "John");
        System.out.println(" The details of Student1 is as follows:");
        student1.displayDetails();
        System.out.println(" Copying student1 to student2 now");
        //Invoking the user-defined copy constructor
        Student student2 = new Student (student1);
        System.out.println(" The details of Student2 is as follows:");
        student2.displayDetails();
    }
}

Output

Here’s the output.
***User defined copy constructor example in Java***
 The details of Student1 is as follows:
 Student name: John,Roll no: 1
 Copying student1 to student2 now
 The details of Student2 is as follows:
 Student name: John,Roll no: 1
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.96