Creational Design Pattern and it’s types

Creational Design Pattern and it’s types

Creational design patterns are a category of design patterns that deal with object creation mechanisms, aiming to create objects in a manner suitable to the situation. These patterns provide various ways to create objects while hiding the creation logic, rather than instantiating objects directly. This makes the system more flexible in deciding which objects need to be created for a given situation.

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

Creational Design Pattern

Advantages of Creational Design Patterns:

1. Encapsulation of instantiation logic: These patterns encapsulate the object creation process, making it easier to manage and modify the code.

2. Promotion of loose coupling: They help in promoting loose coupling by reducing the dependency on specific classes.

3. Enhanced flexibility and reuse: Creational patterns enhance flexibility and reusability by providing alternative ways to create objects.

Types of Creational Design Patterns:

Factory Method

Explanation: The Factory Method pattern defines an interface for creating an object but lets subclasses alter the type of objects that will be created.

Factory Method:
   java
   // Product interface
   interface Product {
       void use();
   }

   // Concrete Products
   class ConcreteProductA implements Product {
       public void use() {
           System.out.println("Using Product A");
       }
   }

   class ConcreteProductB implements Product {
       public void use() {
           System.out.println("Using Product B");
       }
   }

   // Creator
   abstract class Creator {
       public abstract Product factoryMethod();

       public void anOperation() {
           Product product = factoryMethod();
           product.use();
       }
   }

   // Concrete Creators
   class ConcreteCreatorA extends Creator {
       public Product factoryMethod() {
           return new ConcreteProductA();
       }
   }

   class ConcreteCreatorB extends Creator {
       public Product factoryMethod() {
           return new ConcreteProductB();
       }
   }

   // Client
   public class FactoryMethodExample {
       public static void main(String[] args) {
           Creator creatorA = new ConcreteCreatorA();
           creatorA.anOperation();

           Creator creatorB = new ConcreteCreatorB();
           creatorB.anOperation();
       }
   }

2. Abstract Factory

Explanation: The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Example
 java
   // Abstract Factory
   interface GUIFactory {
       Button createButton();
       Checkbox createCheckbox();
   }

   // Concrete Factories
   class WindowsFactory implements GUIFactory {
       public Button createButton() {
           return new WindowsButton();
       }

       public Checkbox createCheckbox() {
           return new WindowsCheckbox();
       }
   }

   class MacOSFactory implements GUIFactory {
       public Button createButton() {
           return new MacOSButton();
       }

       public Checkbox createCheckbox() {
           return new MacOSCheckbox();
       }
   }

   // Product interfaces
   interface Button {
       void click();
   }

   interface Checkbox {
       void check();
   }

   // Concrete Products
   class WindowsButton implements Button {
       public void click() {
           System.out.println("Windows Button Clicked");
       }
   }

   class WindowsCheckbox implements Checkbox {
       public void check() {
           System.out.println("Windows Checkbox Checked");
       }
   }

   class MacOSButton implements Button {
       public void click() {
           System.out.println("MacOS Button Clicked");
       }
   }

   class MacOSCheckbox implements Checkbox {
       public void check() {
           System.out.println("MacOS Checkbox Checked");
       }
   }

   // Client
   public class AbstractFactoryExample {
       private static GUIFactory configureApplication() {
           String osName = System.getProperty("os.name").toLowerCase();
           if (osName.contains("mac")) {
               return new MacOSFactory();
           } else {
               return new WindowsFactory();
           }
       }

       public static void main(String[] args) {
           GUIFactory factory = configureApplication();
           Button button = factory.createButton();
           Checkbox checkbox = factory.createCheckbox();

           button.click();
           checkbox.check();
       }
   }

3. Builder

Explanation: The Builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

Example

   // Product
   class House {
       private String foundation;
       private String structure;
       private String roof;

       public void setFoundation(String foundation) {
           this.foundation = foundation;
       }

       public void setStructure(String structure) {
           this.structure = structure;
       }

       public void setRoof(String roof) {
           this.roof = roof;
       }

       @Override
       public String toString() {
           return "House [foundation=" + foundation + ", structure=" + structure + ", roof=" + roof + "]";
       }
   }

   // Builder Interface
   interface HouseBuilder {
       void buildFoundation();
       void buildStructure();
       void buildRoof();
       House getHouse();
   }

   // Concrete Builder
   class ConcreteHouseBuilder implements HouseBuilder {
       private House house;

       public ConcreteHouseBuilder() {
           this.house = new House();
       }

       public void buildFoundation() {
           house.setFoundation("Concrete Foundation");
       }

       public void buildStructure() {
           house.setStructure("Concrete Structure");
       }

       public void buildRoof() {
           house.setRoof("Concrete Roof");
       }

       public House getHouse() {
           return this.house;
       }
   }

   // Director
   class Director {
       private HouseBuilder houseBuilder;

       public Director(HouseBuilder houseBuilder) {
           this.houseBuilder = houseBuilder;
       }

       public void constructHouse() {
           houseBuilder.buildFoundation();
           houseBuilder.buildStructure();
           houseBuilder.buildRoof();
       }

       public House getHouse() {
           return houseBuilder.getHouse();
       }
   }

   // Client
   public class BuilderExample {
       public static void main(String[] args) {
           HouseBuilder builder = new ConcreteHouseBuilder();
           Director director = new Director(builder);
           director.constructHouse();

           House house = director.getHouse();
           System.out.println(house);
       }
   }
   

4. Prototype

Explanation: The Prototype pattern is used to create a new object by copying an existing object, known as the prototype. It is particularly useful when the cost of creating a new object is expensive.

Example
Example:
   java
   import java.util.HashMap;
   import java.util.Map;

   // Prototype Interface
   interface Prototype extends Cloneable {
       Prototype clone();
   }

   // Concrete Prototype
   class ConcretePrototype implements Prototype {
       private String name;

       public ConcretePrototype(String name) {
           this.name = name;
       }

       public Prototype clone() {
           return new ConcretePrototype(this.name);
       }

       @Override
       public String toString() {
           return "ConcretePrototype [name=" + name + "]";
       }
   }

   // Prototype Registry
   class PrototypeRegistry {
       private Map<String, Prototype> prototypes = new HashMap<>();

       public void addPrototype(String key, Prototype prototype) {
           prototypes.put(key, prototype);
       }

       public Prototype getPrototype(String key) {
           return prototypes.get(key).clone();
       }
   }

   // Client
   public class PrototypeExample {
       public static void main(String[] args) {
           PrototypeRegistry registry = new PrototypeRegistry();
           registry.addPrototype("PrototypeA", new ConcretePrototype("A"));
           registry.addPrototype("PrototypeB", new ConcretePrototype("B"));

           Prototype prototypeA = registry.getPrototype("PrototypeA");
           Prototype prototypeB = registry.getPrototype("PrototypeB");

           System.out.println(prototypeA);
           System.out.println(prototypeB);
       }
   }

5. Singleton

Explanation: The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance.

Example
   java
   public class Singleton {
       private static Singleton instance;

       private Singleton() {
           // private constructor to prevent instantiation
       }

       public static Singleton getInstance() {
           if (instance == null) {
               instance = new Singleton();
           }
           return instance;
       }

       public void showMessage() {
           System.out.println("Hello from Singleton!");
       }
   }

   public class SingletonPatternDemo {
       public static void main(String[] args) {
           Singleton singleton = Singleton.getInstance();
           singleton.showMessage();
       }
   }

Creational Design Pattern Examples

These examples illustrate the primary creational design patterns and how they can be implemented in Java to address various object creation problems. By using these patterns, you can create more flexible, maintainable, and reusable code.

Homepage

Readmore