Prototype design pattern

Yogesh Srivastava
Xebia Engineering Blog

--

What is the design pattern ?

A design pattern is an efficient way to solve a particular class of problem. It is like how a lot of people work and find the best solution for a problem.

Lets talk about prototype design pattern

The Prototype pattern is basically the creation of new instances through cloning existing instances. By creating a prototype, new objects are created by copying this prototype.

It is useful when the object component is already configured once and there is a need for a similar object. The concept of copying an existing object rather than creating a new instance from scratch is a very costly operation. Using a prototype saves costly resources and time especially when the object is very costly to create. An existing object acts as a prototype which contains the state of the object. It is possible that the newly created object may require changes to some of its property.

Let’s have a look on UML of prototype

In this diagram

the prototype is a an interface that defines a function clone()

A real prototype has to implement this interface and implement the clone() function to return a copy of itself.

Lets understand with example :-

Suppose we have a book and bookshop object where the bookshop is fetching all books from the database. So every time we create a new instance of bookshop will result in a query to the database for fetching the record of all books. So to improve the performance will use a prototype pattern .

package com.xebia.prototype.example;public class Book implements Cloneable{private Long id;
private String name;
private String author;
public Book(Long id, String name, String author) {
this.id = id;
this.name = name;
this.author = author;
}
//setters getters@Override
protected Book clone() throws CloneNotSupportedException {
Book book = new Book(this.id, this.name, this.author);
return book;
}
}package com.xebia.prototype.example;import java.util.ArrayList;
import java.util.List;
public class BookShop implements Cloneable { private String name;
private List<Book> books;
public BookShop() {
this.books = new ArrayList<>();
}
public void initialize() {
// let’s suppose list is coming from database
for (int i = 0; i < 10; i++) {
Book book = new Book(Long.valueOf(i), “Book-” + i, “Author-” + i);
this.books.add(book);
}
}
@Override
protected BookShop clone() throws CloneNotSupportedException {
BookShop shop = new BookShop();
for (Book book : this.getBooks()) { shop.getBooks().add(book.clone());
}
return shop;
}
//setters getters
}
public class BookTest {public static void main(String[] args) throws CloneNotSupportedException {
BookShop bookShop = new BookShop(“Xebia Shop India”);
bookShop.initialize();
System.out.println(bookShop);
BookShop bookShop2 = bookShop.clone();
bookShop2.setName(“Xebia Shop DUbai”);
System.out.println(bookShop2);
}
}

After looking into the code above we can see for the first time when we are creating a bookshop it’s fetching all the books from the database. Next time when we create a new instance by cloning the bookshop object it is fetching data from the first object. So that is the way we can create multiple instances of the bookshop.

Object cloning can be done in two ways:-

  1. Shallow cloning
  2. Deep cloning

When we use the default clone method, it will create a shallow copy of the object. It means the cloned object will have the same state as the source object. In shallow cloning only memory addresses are copied if any changes made in the field of the object will reflect to the cloned object as well. It works similar to deep cloning in case of primitives

A deep cloning object will have the same state as shallow cloning but the original and cloned object will be fully disjoint. They will be independent of each other. If there is any change made to the clone object it will not be reflected in the original object or vice-versa.

In the above example we have used deep cloning of book to ensure that every bookshop can be independent of each other.

Where to use

  • When a system needs to be independent of how its objects are created, composed, and represented.
  • When adding and removing objects at runtime.
  • When specifying new objects by changing an existing objects structure.
  • When configuring an application with classes dynamically.
  • When trying to keep the number of classes in a system to a minimum.
  • When state population is an expensive or exclusive process.

Benefits

  • Speeds up instantiation of large, dynamically loaded classes.
  • Reduced subclassing.

Drawbacks/consequences

  • Each subclass of Prototype must implement the Clone operation.
  • Could be difficult with existing classes which do not support copying.

That’s it for this blog post. I hope you found it useful and stay tuned for more 😀

--

--