Search Knowledge

© 2026 LIBREUNI PROJECT

Software Engineering & OOAD / Design Patterns

Singleton & Factory Patterns

Singleton & Factory Patterns

Design patterns are reusable solutions to common problems in software design. We begin our exploration with Creational Patterns, which handle object creation mechanisms, trying to create objects in a manner suitable to the situation.


1. The Singleton Pattern

The Problem

Sometimes you need exactly one instance of a class. For example, a configuration manager, a thread pool, or a database connection pool. If multiple instances are created, it could lead to inconsistent state or wasted resources.

The Solution

The Singleton pattern ensures a class has only one instance and provides a global point of access to it. It achieves this by:

  1. Making the constructor private.
  2. Providing a static method that returns the single instance.

Java Implementation (Thread-Safe)

public class DatabaseConnector {
    // 1. Private static instance
    private static volatile DatabaseConnector instance;

    // 2. Private constructor
    private DatabaseConnector() {
        // Initialize connection here
    }

    // 3. Static access method with Double-Checked Locking
    public static DatabaseConnector getInstance() {
        if (instance == null) {
            synchronized (DatabaseConnector.class) {
                if (instance == null) {
                    instance = new DatabaseConnector();
                }
            }
        }
        return instance;
    }

    public void query(String sql) {
        System.out.println("Executing: " + sql);
    }
}

Pros and Cons

  • Pros: Controlled access to a single instance, reduced memory footprint.
  • Cons: Can be difficult to unit test (global state), can hide dependencies.

2. The Factory Method Pattern

The Problem

Imagine a logistics app that initially only handles truck transport. If you want to add maritime transport, you’d have to change a lot of code everywhere you instantiate a Truck. Direct instantiation (new Truck()) couples your code to specific classes.

The Solution

The Factory Method pattern defines an interface for creating an object but lets subclasses decide which class to instantiate.

Python Example

from abc import ABC, abstractmethod

# Product Interface
class Transport(ABC):
    @abstractmethod
    def deliver(self):
        pass

# Concrete Products
class Truck(Transport):
    def deliver(self):
        return "Delivering by land in a box."

class Ship(Transport):
    def deliver(self):
        return "Delivering by sea in a container."

# Creator (Factory)
class Logistics(ABC):
    @abstractmethod
    def create_transport(self) -> Transport:
        pass

    def plan_delivery(self):
        transport = self.create_transport()
        return f"Logistics: {transport.deliver()}"

# Concrete Creators
class RoadLogistics(Logistics):
    def create_transport(self) -> Transport:
        return Truck()

class SeaLogistics(Logistics):
    def create_transport(self) -> Transport:
        return Ship()

# Usage
logistics = RoadLogistics()
print(logistics.plan_delivery())

When to use Factory Method?

  • When a class can’t anticipate the class of objects it must create.
  • When you want to provide users of your library with a way to extend its internal components.

3. Abstract Factory (Bonus)

While the Factory Method creates one product, the Abstract Factory creates families of related products.

Imagine a UI toolkit that needs to create Buttons, Checkboxes, and Sliders. You might have a WindowsFactory and a MacFactory. Each factory produces a set of components that “match” each other.

Key Difference

  • Factory Method: One method, one product.
  • Abstract Factory: Many methods, many related products.

Comparison Summary

PatternFocusUse Case
SingletonUniquenessResource managers, global state.
Factory MethodSubclassingWhen exact types are determined by subclasses.
Abstract FactoryFamiliesWhen products must work together (themes, OS).