Factory Design Pattern in Java

1. Definition

The Factory Design Pattern is a creational design pattern that provides an interface for creating objects but allows subclasses to alter the type of objects that will be created. Instead of calling a constructor directly, a factory method is used to create the desired object, abstracting the object creation process.

2. Problem Statement

Imagine an application where you need to create objects of various classes based on some input or configuration. Direct instantiation using constructors can lead to system rigidity, making it hard to extend, modify, or interchange components in the future.

3. Solution

The Factory Pattern comes to the rescue by providing a separate method for the creation of objects. This method can be overridden, allowing the creation of different types of objects based on the input. This promotes loose coupling, making the system more modular and easier to extend.

4. Real-World Use Cases

1. GUI libraries where each operating system provides a different implementation of a button or a window.

2. E-commerce platforms offer multiple payment gateways, where each gateway has a different process.

3. Database connection pools where connections to different types of databases need to be created based on configuration.

5. Implementation Steps

1. Define a common interface or abstract class for the product.

2. Implement different concrete classes of the product.

3. Create a factory class that has a method to return an instance of the product based on a given input.

6. Implementation

// Step 1: Define a common product interface.
interface Drink {
    void prepare();
}

// Step 2: Implement concrete classes of the product.
class Coffee implements Drink {
    @Override
    public void prepare() {
        System.out.println("Preparing coffee.");
    }
}

class Tea implements Drink {
    @Override
    public void prepare() {
        System.out.println("Preparing tea.");
    }
}

// Step 3: Define the factory and provide its concrete implementation.
class DrinkFactory {
    public Drink getDrink(String drinkType) {
        if (drinkType == null) {
            return null;
        }
        if (drinkType.equalsIgnoreCase("COFFEE")) {
            return new Coffee();
        } else if (drinkType.equalsIgnoreCase("TEA")) {
            return new Tea();
        }
        return null;
    }
}

// Demonstrate the Factory Design Pattern.
public class FactoryPatternIllustration {
    public static void main(String[] args) {
        DrinkFactory drinkFactory = new DrinkFactory();

        Drink drink1 = drinkFactory.getDrink("COFFEE");
        drink1.prepare();

        Drink drink2 = drinkFactory.getDrink("TEA");
        drink2.prepare();
    }
}

Output:

Preparing coffee.
Preparing tea.

Explanation

In the given example:

1. Drink is the common product interface with a method prepare().

2. Coffee and Tea are concrete implementations of the Drink interface.

3. DrinkFactory is the factory class that returns an instance of either Coffee or Tea based on the input string.

4. The FactoryPatternIllustration class demonstrates how to use the factory to obtain and use product instances.

Using the Factory pattern, we can seamlessly introduce more drink types in the future without changing the client code. This ensures the system adheres to the Open/Closed Principle – it remains open for extension but closed for modification.

7. When to use?

1. When the exact type of the object isn't known until runtime.

2. When the creation process is more involved than just instantiation.

3. When a system needs to be independent of how its objects are created and represented.

The Factory Design Pattern promotes code reusability, flexibility, and system modularity, making it a valuable tool in a developer's toolkit.


Comments