A GUIDE TO SOFTWARE DESIGN PATTERNS

Creational Design Pattern: Prototype

Design Pattern Part 5

Petey
Petey
Jan 15 · 3 min read
Photo by Alex wong on Unsplash

The prototype pattern is one of the five creational patterns that is used when the creation of new objects is done by cloning an existing instance.

In plain English, this simply means you don’t use the new keyword to create a new instance, rather a deep-cloning of an existing object is performed. This pattern is used for a few reasons, but the most important one is to avoid the expensive cost of creating new objects the standard way in some applications — e.g., using the ‘new’ keyword.

Some applications load data from a data source and it can be anything from a database, a file, etc… If your application needs to load data, then loading that same information each time you create a new object can be time-consuming and or memory intensive depending on the size. This is where the prototype pattern comes in handy.


For instance, you’re tasked to design and implement a package that creates Staff. Staff includes professors, assistants, custodians, interns, etc… Your staff object needs to be able to return all staff members’ names and perform a lookup by name. We’re going to assume that all names in our data source are unique. Now imagine having to make a call to load the staff members’ data every time you create a new object. That can be quite an expensive operation. We can use the prototype pattern to solve this problem.

For an object to be cloneable, it needs to implement the Cloneable interface. We need to override the clone method to perform a deep-copy of the object being cloned. If you’re not familiar with the cloning concept, I suggest you check out The Difference Between Shallow And Deep Copy.


We won’t be reading data from a data source in the sample, rather we’ll hardcode some values for brevity’s sake. The code for the Staff class would look like this.

public class Staff implements Cloneable {
private List<String> staffNames;
public Staff(){
this.staffNames = new ArrayList<>();
loadStaffNames();
}
//simulates a database call to get all staff names
private void loadStaffNames(){
this.staffNames.add("Michael Bublé");
this.staffNames.add("Frank Sinatra");
this.staffNames.add("Mile Davis");
this.staffNames.add("Louis Armstrong");
this.staffNames.add("Nat King Cole");
}
public List<String> getStaffNames(){
return this.staffNames;
}

public String findStaffByName(String name){
return this.staffNames
.stream()
.filter(x -> x.equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
@Override
public Object clone() throws CloneNotSupportedException{
Staff copiedStaff = (Staff)super.clone();
this.staffNames.stream().forEach(
x -> copiedStaff.staffNames.add(x));
return copiedStaff;
}
}

In this our Staff class, the costly operation is performed in the loadStaffNames method, which is a private method that gets called each time an object is created using the new keyword. So if you need to create an object with the same data, there is no need to reload the data again. This pattern provides a way to create instances by cloning an existing object.

In the findStaffByName method, we also used the same loaded data to perform the search. If your application requires a way to reload the data from the database or whatever data source being used, then your class can provide a method to do that.

You still need to create at least one object using the new keyword. Cloning something implies there’s an original or existing object. Once you have an existing object, then you can clone it whenever you want another instance of a class instead of creating a new one from scratch. You want to do that because creating a new one would make another call to the database in our case — or whatever costly operation you’re trying to limit.

You can then use your Staff class and clone is like this.

public static void main(String[] args)  {    try {
Staff staff = new Staff();
System.out.println("number of staff in: "
+ staff.getStaffNames().size());
Staff copiedStaff = (Staff)staff.clone(); System.out.println("number of staff: "
+ copiedStaff.getStaffNames().size());
System.out.println(staff.hashCode());
System.out.println(copiedStaff.hashCode());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
//---------------output----------------number of staff: 5
number of staff: 5
2114889273
1025799482

There are always pros and cons to every solution. Always remember there isn’t just one solution to solve every problem. So use your best judgment when considering this pattern.

Thank you for making it to the end. Happy coding.

Previous: Creational Design Pattern: Abstract Factory

Petey

Written by

Petey

Husband, father, engineer, musician, and writer by luck. I write mostly about whatever comes to mind. Follow me on this crazy writing journey if you dare.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade