Learn about

Creational Design Patterns

and become a better Developer | Day 4 — #100DaysOfCode

Dhananjay Trivedi

--

As you gain experience while coding up something you will see everyone develops their own coding pattern. Their own way of naming the packages, refactoring classes, renaming variables. I am sure you don't want them all to work together on a project. The project will be full of God classes that is One-Class — Do-All and when it comes to making some changes you cant make some change without breaking hundreds of other things. This is where Design Patterns will help us all.

Design Patterns are like an established solution to the most commonly encountered problems in software development. You and your team depending upon your system can decide and follow the design patterns and maintain a uniform, clean, easy to understand, maintainable codebase.

Today we will be looking into some “Creational Design Patterns”. They are concerned with how we create objects. They help us control the way our code will be instantiating objects.

1. Object Pool Pattern

Some objects might be heavy/expensive to instantiate, hence you don’t want to invoke them with every ‘new’ call as they heavily impact the performance of your system. This is great for systems which have an expensive process of instantiating objects and a high rate of instantiating those objects.a

Hence, we try to reuse the objects which were already created instead of instantiating them frequently.

Resource Pool is used to manage the object caching. The client will ask the resource pool for the object’s instance. The pool will either allocate the client with an already existing instance which is not being used. Else, it will instantiate a new instance and allocate the client with the new instance. This new instance will also be added to the pool once it becomes free and hence the Resource Pool size will be growing.

The Resource Pool class itself a class that is created using a Singleton Design Pattern.

A Bad Example, There is a company which gives a laptop to its talent as they join. Once the talent joins, the company will see its inventory if there are any laptops available which can be assigned to the talent. If there are no laptops available then only the company will buy a new laptop. As the talent leaves the company, he returns the laptop and the laptop is again sent back to the inventory which can be reused by any future/existing talents.

Pros?

  • Boosts the performance of applications significantly.
  • Gives you control over the instantiation of expensive objects, hence you can control how many active objects will be created.

Where to Use?

  • Situations where you cannot afford to instantiate objects frequently. For example Database connections.
  • Resource sharing is to be done in a controlled manner.C

2. Prototype Pattern

Ever observe how applications like Instagram evolve over time? The developers create an MVP which gets funded and over time they iterate over it and keep on adding more and more features on it as per the requirements. Whenever there is a new requirement they don’t build a new application from scratch, they build something on top of the existing project.

Similarly, the concept is to copy an existing object rather than creating a new instance from scratch, something that may include costly operations. This approach saves costly resources and time, especially when the object creation is a heavy process.

We know the most efficient way to copy an object is to clone() it. But if you want to change some properties of the object while copying it, you are free to write a clone() method of your own.

Pros

  • The Prototype pattern lets you clone a prototype instead of asking a factory method to make a new object.
  • Works perfectly fine with the runtime as you can avoid creating new objects.
  • Improves program efficiency as it helps you avoid creating new instances through heavy operation.

3. Factory Pattern

One of the most popular creational design pattern. This defines an interface for creating an object, and the subclasses have the flexibility to decide which classes to instantiate. Interface abstracts away the instantiation logic from the client.

Let’s take a look at a bad example, here we are abstracting the user away with DatabaseFactory class from directly instantiating any of the following Database instances. Depending upon what databaseUrl is sent to getDatabase() of DatabaseFactory.

public class DatabaseFactory {
public DatabaseInstance getDatabase(String databaseUrl){
if(databaseUrl == null){
return null;
}
if(databaseUrl.equalsIgnoreCase("URL1")){
return new UsersDatabase(databaseUrl);
}
if(databaseUrl.equalsIgnoreCase("URL2")){
return new OrdersDatabase(databaseUrl);
}
if(databaseUrl.equalsIgnoreCase("URL3")){
return new ItemsDatabase(databaseUrl);
}
return null;
}
}
//P.S. You can use switch case if you like...

Pros

  • Here we are able to achieve loose coupling between the client and the database classes which is really essential for building good software systems. This makes your system less fragile to break as there are some changes made in either of the classes.
  • The creation of an object requires access to information or resources that should not be contained within the composing class as it violates the Single Responsibility Principle.

Hope you will apply what you learn and explore more about these Design Patterns.

--

--