top of page

Creational Design Pattern

  • Writer: Anand Nerurkar
    Anand Nerurkar
  • May 2, 2024
  • 8 min read

Creational Design Patterns are concerned with the way in which objects are created. They reduce complexities and instability by creating objects in a controlled manner.


The new operator is often considered harmful as it scatters objects all over the application. Over time it can become challenging to change an implementation because classes become tightly coupled.


Creational Design PAttern

====

Singleton – Ensures that at most only one instance of an object exists throughout application.


public class Singleton  {

private Singleton() {}

private static class SingletonHolder {

public static final Singleton instance = new Singleton();

}

public static Singleton getInstance() { return SingletonHolder.instance; } }


When to Use Singleton Design Pattern

  • For resources that are expensive to create (like database connection objects)

  • It’s good practice to keep all loggers as Singletons which increases performance

  • Classes which provide access to configuration settings for the application

  • Classes that contain resources that are accessed in shared mode


Any class which you want to be available to whole application and whole only one instance is viable is candidate of becoming Singleton. One example of this is Runtime class , since on whole java application only one runtime environment can be possible making Runtime Singleton is right decision. Another example is a utility classes like Popup in GUI application, if you want to show popup with message you can have one PopUp class on whole GUI application and anytime just get its instance, and call show() with message.


How many ways you can write Singleton Class in Java?

Answer : I know at least four ways to implement Singleton pattern in Java


  1. Singleton by synchronizing getInstance() method

  2. Singleton with public static final field initialized during class loading.

  3. Singleton generated by static nested class, also referred as Singleton holder pattern.

  4. From Java 5 on-wards using Enums



When to choose Singleton over Static Class?

The choice between a Singleton and a Static Class hinges on the nature of your application's requirements. Opt for a Singleton when you need to ensure a single instance of a class and a centralized point of access. 

It's valuable for managing shared resources like configuration settings or connection pools. Singleton also supports lazy initialization, creating the instance only when necessary. 

On the other hand, a Static Class is fitting for situations where you have a collection of related utility functions or constants that don't rely on instance-specific state. 

These classes encapsulate stateless operations and are accessed through the class itself, making them suitable for grouping related functionalities. The decision ultimately boils down to the specific needs and design principles of your project.



How do you prevent for creating another instance of Singleton during serialization?

Another great question which requires knowledge ofSerialization in Javaand how to use it for persisting Singleton classes. This is open to you all but in my opinion use of readResolve() method can sort this out for you.


Answer: You can prevent this by usingreadResolve()method, since during serializationreadObject()is used to create instance and it return new instance every time but by using readResolve you can replace it with original Singleton instance. I have shared code on how to do it in my post Enum as Singleton in Java. This is also one of the reason I have said that use Enum to create Singleton because serialization of enum is taken care by JVM and it provides guaranteed of that.



How do you prevent for creating another instance of Singleton using clone() method?

This type of questions generally comes some time by asking how to break singleton or when Singleton is not Singleton in Java.


Answer : Preferred way is not to implement Cloneable interface as why should one wants to create clone() of Singleton and if you do just throw Exception from clone() method as “Can not create clone of Singleton class”.


Give me some examples of Singleton pattern from Java Development Kit?

This is open question to all, please share which classes are Singleton in JDK. Answer to this question is java.lang.Runtime

Answer : There are many classes in Java Development Kit which is written using singleton pattern, here are few of them:


  1. Java.lang.Runtime with getRuntime() method 

  2. Java.awt.Toolkit with getDefaultToolkit() 

  3. Java.awt.Desktop with getDesktop() 




What is double checked locking in Singleton?

One of the most hyped question on Singleton pattern and really demands complete understanding to get it right because of Java Memory model caveat prior to Java 5. If a guy comes up with a solution of using volatile keyword with Singleton instance and explains it then it really shows it has in depth knowledge of Java memory model and he is constantly updating his Java knowledge.



Answer : Double checked locking is a technique to prevent creating another instance of Singleton when call to getInstance() method is made in multi-threading environment. In Double checked locking pattern as shown in below example, singleton instance is checked two times before initialization. See here to learn more about double-checked-locking in Java. 


public static Singleton getInstance(){
     if(_INSTANCE == null){
         synchronized(Singleton.class){
         //double checked locking - because second check of Singleton instance with lock
                if(_INSTANCE == null){
                    _INSTANCE = new Singleton();
                }
            }
         }
     return _INSTANCE;
}

Double checked locking should only be used when you have requirement for lazy initialization otherwise use Enum to implement singleton or simple static final variable.



Factory Method – Creates objects of several related classes without specifying the exact object to be created

The Factory Design Pattern or Factory Method Design Pattern is one of the most used design patterns in Java.

According to GoF, this pattern “defines an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses”.

This pattern delegates the responsibility of initializing a class from the client to a particular factory class by creating a type of virtual constructor.

To achieve this, we rely on a factory which provides us with the objects, hiding the actual implementation details. The created objects are accessed using a common interface.


Factory Method Design Pattern Example

In this example, we’ll create a Polygon interface which will be implemented by several concrete classes. A PolygonFactory will be used to fetch objects from this family:

Let’s first create the Polygon interface:

public interface Polygon {
    String getType();
}Copy

Next, we’ll create a few implementations like Square, Triangle, etc. that implement this interface and return an object of Polygon type.

Now we can create a factory that takes the number of sides as an argument and returns the appropriate implementation of this interface:

public class PolygonFactory {
    public Polygon getPolygon(int numberOfSides) {
        if(numberOfSides == 3) {
            return new Triangle();
        }
        if(numberOfSides == 4) {
            return new Square();
        }
        if(numberOfSides == 5) {
            return new Pentagon();
        }
        if(numberOfSides == 7) {
            return new Heptagon();
        }
        else if(numberOfSides == 8) {
            return new Octagon();
        }
        return null;
    }
}Copy

Notice how the client can rely on this factory to give us an appropriate Polygon, without having to initialize the object directly.


When to Use Factory Method Design Pattern

  • When the implementation of an interface or an abstract class is expected to change frequently

  • When the current implementation cannot comfortably accommodate new change

  • When the initialization process is relatively simple, and the constructor only requires a handful of parameters


Abstract Factory – Creates families of related dependent objects


Builder – Constructs complex objects using step-by-step approach

The builder pattern is a creational design pattern used to assemble complex objects. With the builder pattern, the same object construction process can be used to create different objects. The builder has 4 main parts: a Builder, Concrete Builders, a Director, and a Product.


A Builder is an interface (or abstract class) that is implemented (or extended) by Concrete Builders. The Builder interface sets forth the actions (methods) involved in assembling a Product object. It also has a method for retrieving the Product object (ie, getProduct()). The Product object is the object that gets assembled in the builder pattern.


Concrete Builders implement the Builder interface (or extend the Builder abstract class). A Concrete Builder is responsible for creating and assembling a Product object. Different Concrete Builders create and assemble Product objects differently.


A Director object is responsible for constructing a Product. It does this via the Builder interface to a Concrete Builder. It constructs a Product via the various Builder methods.

There are various uses of the builder pattern. For one, if we'd like the construction process to remain the same but we'd like to create a different type of Product, we can create a new Concrete Builder and pass this to the same Director. If we'd like to alter the construction process, we can modify the Director to use a different construction process.


code sample

==

the product- Meal to be built

public class Meal { private String drink; private String mainCourse; private String side; public String getDrink() { return drink; } public void setDrink(String drink) { this.drink = drink; } public String getMainCourse() { return mainCourse; } public void setMainCourse(String mainCourse) { this.mainCourse = mainCourse; } public String getSide() { return side; } public void setSide(String side) { this.side = side; } public String toString() { return "drink:" + drink + ", main course:" + mainCourse + ", side:" + side; } }


Builder interface- set forth action to constrcut a product

public interface MealBuilder { public void buildDrink(); public void buildMainCourse(); public void buildSide(); public Meal getMeal(); }


Our first Concrete Builder is ItalianMealBuilder. Its constructor creates a meal. Its methods are implemented to build the various parts of the meal. It returns the meal via getMeal().

public class ItalianMealBuilder implements MealBuilder { private Meal meal; public ItalianMealBuilder() { meal = new Meal(); } @Override public void buildDrink() { meal.setDrink("red wine"); } @Override public void buildMainCourse() { meal.setMainCourse("pizza"); } @Override public void buildSide() { meal.setSide("bread"); } @Override public Meal getMeal() { return meal; } }


Our second Concrete Builder is JapaneseMealBuilder. Its constructor creates a meal. Its methods are implemented to build the various parts of a Japanese meal. It returns the meal via getMeal().



public class JapaneseMealBuilder implements MealBuilder {

	private Meal meal;

	public JapaneseMealBuilder() {
		meal = new Meal();
	}

	@Override
	public void buildDrink() {
		meal.setDrink("sake");
	}

	@Override
	public void buildMainCourse() {
		meal.setMainCourse("chicken teriyaki");
	}

	@Override
	public void buildSide() {
		meal.setSide("miso soup");
	}

	@Override
	public Meal getMeal() {
		return meal;
	}

}

Our Director class is MealDirector. It takes a MealBuilder as a parameter in its constructor. Thus, a different type of meal will be assembled by the MealDirector depending on the Concrete Builder passed in to the constructor. The assembly of the meal (Product) takes place in the constructMeal() method of the Director. This method spells out the parts of the meal that will be assembled.



public class MealDirector {

	private MealBuilder mealBuilder = null;

	public MealDirector(MealBuilder mealBuilder) {
		this.mealBuilder = mealBuilder;
	}

	public void constructMeal() {
		mealBuilder.buildDrink();
		mealBuilder.buildMainCourse();
		mealBuilder.buildSide();
	}

	public Meal getMeal() {
		return mealBuilder.getMeal();
	}

}

The Demo class lets us demonstrate our builder pattern. First, our director builds an Italian meal. An ItalianMealBuilder is passed to the MealDirector's constructor. The meal is constructed via mealDirector.constructMeal(). The meal is obtained from mealDirector via mealDirector.getMeal(). The Italian meal is displayed. After this, we perform the same process to build and display a Japanese meal.



public class Demo {

	public static void main(String[] args) {

		MealBuilder mealBuilder = new ItalianMealBuilder();
		MealDirector mealDirector = new MealDirector(mealBuilder);
		mealDirector.constructMeal();
		Meal meal = mealDirector.getMeal();
		System.out.println("meal is: " + meal);
		
		mealBuilder = new JapaneseMealBuilder();
		mealDirector = new MealDirector(mealBuilder);
		mealDirector.constructMeal();
		meal = mealDirector.getMeal();
		System.out.println("meal is: " + meal);
	}

}

Prototype

==

The prototype pattern is a creational design pattern. In the prototype pattern, a new object is created by cloning an existing object. In Java the clone() method is an implementation of this design pattern.


The prototype pattern can be a useful way of creating copies of objects. One example of how this can be useful is if an original object is created with a resource such as a data stream that may not be available at the time that a clone of the object is needed.


Another example is if the original object creation involves a significant time commitment, such as reading data from a databaseW or over a network. An added benefit of the prototype pattern is that it can reduce class proliferation in a project by avoiding factory proliferation.



 
 
 

Recent Posts

See All

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
  • Facebook
  • Twitter
  • LinkedIn

©2024 by AeeroTech. Proudly created with Wix.com

bottom of page