A Complete Guide to Creational Design Patterns in Java: The Prototype Pattern

Varsha Das
4 min readSep 22, 2022

What is a design pattern?

A software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design.

Why should I learn patterns?

Makes life simpler by not reinventing the wheel

  1. Toolbox of time-tested solutions to common problems in software design.
  2. Defines a common language between the team and organization to solve emerging issues related to technological advancements.
  3. Start understanding patterns in libraries and languages.

Classification of patterns

Creational

Structural

Behavioral

There are 5 main types of Creational Design patterns:

  1. Builder
  2. Prototype
  3. Singleton
  4. Factory
  5. Abstract Factory

In this article, we will focus in detail on one of the Creational patterns — The Prototype Design pattern.

Usage:

Create copies of existing objects considering resource constraints.

Used when the creation of objects, again and again, is resource-intensive.

Existing problem:

We have an object, and we want to create an exact copy of it.

What shall we do? — Create a new object.

As mentioned above, the creation of new objects can be memory-intensive and we might also want to modify the newer objects.

How can the Prototype pattern help?

Using cloning concept — to make copies of the original object.

The original object that supports cloning is called a prototype.

Instead of writing code that invokes the “new” operator on a hard-coded class name, we call the clone() method on the prototype.

The only catch is, this pattern is most useful when required objects to be created are of similar type or same.

In Java, we use the Cloneable interface and override the built-in clone() method to create an object from an existing object. It is the simplest way to implement a prototype pattern.

Code with an example:

We have an employee class and the main class that loads data for employees and prints them.

Below is the Employee class:

For loading the employee data, we need to fetch that from the database and that’s a costly operation to do every time. So we have another EmployeeRecord class that will deal with how to get the list of employees and perform data manipulation on that.

Below is the Employee Record class:

In the loadEmployees() method, we should ideally have the logic to make DB connections & get employee data . However, for now we just have a hard-coded placeholder logic for doing the same.

Below is the main class:

Here, we first print all the employees.

Output:

Now, we will use the clone() method to create a clone of the existing empRecord instance.

Here is the updated EmployeeRecord class where we add the Cloneable interface and override the clone() method:

Here is the updated code of the Client

Output:

As we can see, instead of doing another loadEmployees() method call, we clone the existing object and get exact same results.

But, there’s an issue with the above code.

Here we introduce another concept called ‘shallow cloning’.

What is Shallow cloning?

The default version of the clone method creates a shallow copy of an object.

The cloned object also refers to the same object to which the original object refers as only the object references get copied and not the referred objects themselves. In simpler terms, one object is being created here while two references are in the stack memory.

@Override
protected EmployeeRecord clone() {
try {
return (EmployeeRecord) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}

As we can see in the above clone() method, it returns it as an object type, we need to explicitly cast it back to our original object. This is a shallow copy of the object.

As a result of this, any changes made to the existing object will also get reflected in the cloned object. This should not be the case.

What is the workaround for this? — deep cloning.

What is deep cloning?

Instead of object references getting copied, we clone the original object with its values.

So after copying, both the objects are independent of each other.

Hence, if we make any changes in the original object, that change does not get reflected in the other object.

Here is the updated EmployeeRecord class.

We remove the super.clone() method and write logic to copy elements from original object with values.

In the below Client class, we manipulate the original object by removing 1 employee from it.

Output:

As we can see above, in the original object empid=4 is removed, but in the cloned object all the employees appear. This clearly depicts that due to deep cloning, 2 separate objects are now being dealt with.

Thus changes in original object doesn’t affect the cloned object.

If you liked this article, please click the “clap” button 👏 a few times.

Gives me enough motivation to put out more content like this. Please share it with a friend who you think this article might help.

Follow me Varsha Das to receive my weekly articles.

Connect with me — Varsha Das | LinkedIn

Follow my Youtube channel — Code With Ease — By Varsha, where we discuss Data Structures & Algorithms, software engineering concepts and much more.

Thanks for reading.

Happy learning! 😁

--

--

Varsha Das

"Senior Software Engineer @Fintech | Digital Creator @Youtube | Thrive on daily excellence | ❤️ complexity -> clarity | Devoted to health and continuous growth