Creational Design Patterns

Rohan SarnadRohan Sarnad
5 min read

Factory Pattern

What is the Factory Pattern?

The Factory Pattern is a creational design pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created. This helps decouple object creation from the main logic of the application.

When to Use the Factory Pattern?

  • When the exact type of object to be created is determined dynamically at runtime.

  • When the instantiation process is complex and needs to be abstracted.

  • When promoting loose coupling in code by delegating object creation to a factory class.

Real-World Example: Payment Processing System

Imagine an application supporting multiple payment methods (Credit Card, net banking, UPI). Instead of creating objects manually, a PaymentFactory class can generate the correct payment processor dynamically.

Implementation in Java

// Step 1: Define an Abstract Class
abstract class Payment {
    abstract void processPayment(double amount);
}

// Step 2: Implement Concrete Classes
class CreditCardPayment extends Payment {
    @Override
    void processPayment(double amount) {
        System.out.println("Processing Credit Card payment of rupees " + amount);
    }
}

class UPIPayment extends Payment {
    @Override
    void processPayment(double amount) {
        System.out.println("Processing UPI payment of rupees " + amount);
    }
}

class NetBankingPayment extends Payment {
    @Override
    void processPayment(double amount) {
        System.out.println("Processing Net Banking payment of rupees " + amount);
    }
}

// Step 3: Create a Factory Class
class PaymentFactory {
    public static Payment getPaymentMethod(String methodType) {
        if (methodType.equalsIgnoreCase("credit")) {
            return new CreditCardPayment();
        } else if (methodType.equalsIgnoreCase("upi")) {
            return new UPIPayment();
        } else if (methodType.equalsIgnoreCase("netbanking")) {
            return new NetBankingPayment();
        } else {
            throw new IllegalArgumentException("Invalid payment method");
        }
    }
}

// Step 4: Using the Factory Pattern
public class FactoryPattern {
    public static void main(String[] args) {
        Payment paymentMethod = PaymentFactory.getPaymentMethod("credit");
        paymentMethod.processPayment(100.0);
    }
}

Singleton Pattern

What is the Singleton Pattern?

The Singleton Pattern ensures that a class has only one instance and provides a global point of access to that instance. This is useful for managing shared resources like database connections, logging, or configuration settings.

When to Use the Singleton Pattern?

  • When exactly one instance of a class is required across the system.

  • When global access to an object is needed, such as configuration managers or logging services.

  • When controlling access to shared resources like a thread pool or database connection.

Implementation in Java

// Step 1: Define the Singleton Class
class Singleton {
    // Private static instance of the class
    private static Singleton instance;

    // Private constructor to restrict instantiation
    private Singleton() {}

    // Public method to provide global access
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void showMessage(String objectName) {
        System.out.println("Singleton Instance: Hello " + objectName);
    }
}

// Step 2: Using the Singleton Pattern
public class SingletonPatternExample {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        // Display message
        singleton1.showMessage("singleton1");
        singleton2.showMessage("singleton2");
        // Check if both references point to the same instance
        System.out.println("Are both instances the same? " + (singleton1 == singleton2));
    }
}

Builder Pattern

What is the Builder Pattern?

The Builder Pattern is a creational design pattern that allows step-by-step object construction while keeping the object immutable and readable. It is useful when objects have multiple optional attributes.

Implementation in Java

// Step 1: Define the Product Class
class Car {
    private String engine;
    private int wheels;
    private boolean sunroof;

    // Private constructor to enforce object creation via Builder
    private Car(CarBuilder builder) {
        this.engine = builder.engine;
        this.wheels = builder.wheels;
        this.sunroof = builder.sunroof;
    }

    public String toString() {
        return "Car with " + engine + ", " + wheels + " wheels, sunroof: " + sunroof;
    }

    // Builder Class
    static class CarBuilder {
        private String engine;
        private int wheels;
        private boolean sunroof;

        public CarBuilder setEngine(String engine) {
            this.engine = engine;
            return this;
        }
        public CarBuilder setWheels(int wheels) {
            this.wheels = wheels;
            return this;
        }
        public CarBuilder setSunroof(boolean sunroof) {
            this.sunroof = sunroof;
            return this;
        }
        public Car build() {
            return new Car(this);
        }
    }
}

class CarBuilderExample {
    public static void main(String[] args) {
        Car car = new Car.CarBuilder()
                .setEngine("Hyundai")
                .setWheels(4)
                .setSunroof(true)
                .build();
        System.out.println(car);
    }
}

Prototype Pattern

What is the Prototype Pattern?

The Prototype Pattern is a creational design pattern that allows the creation of new objects by copying an existing object, instead of instantiating new ones. This pattern helps improve performance when object creation is expensive.

When to Use the Prototype Pattern?

  • When object creation is costly and needs to be optimized.

  • When you want to avoid repetitive initialization of objects.

  • When an application requires multiple instances of an object with minimal modifications.

Real-World Example: Cloning Shapes

Imagine a drawing application where different shapes (Circle, Rectangle) need to be duplicated frequently. Instead of creating new instances from scratch, we can use the Prototype Pattern to clone existing shapes.

Implementation in Java

// Step 1: Define a Prototype Interface
interface Prototype {
    Prototype clone();
}

// Step 2: Create Concrete Classes
class Circle implements Prototype {
    private int radius;

    public Circle(int radius) {
        this.radius = radius;
    }

    @Override
    public Prototype clone() {
        return new Circle(this.radius);
    }

    @Override
    public String toString() {
        return "Circle with radius: " + radius;
    }
}

class Rectangle implements Prototype {
    private int width, height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public Prototype clone() {
        return new Rectangle(this.width, this.height);
    }

    @Override
    public String toString() {
        return "Rectangle with width: " + width + ", height: " + height;
    }
}

// Step 3: Using the Prototype Pattern
public class PrototypePatternExample {
    public static void main(String[] args) {
        Circle originalCircle = new Circle(10);
        Circle clonedCircle = (Circle) originalCircle.clone();

        Rectangle originalRectangle = new Rectangle(20, 30);
        Rectangle clonedRectangle = (Rectangle) originalRectangle.clone();

        System.out.println("Original: " + originalCircle);
        System.out.println("Cloned: " + clonedCircle);

        System.out.println("Original: " + originalRectangle);
        System.out.println("Cloned: " + clonedRectangle);
    }
}
0
Subscribe to my newsletter

Read articles from Rohan Sarnad directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rohan Sarnad
Rohan Sarnad