Open In App

Factory Method | Java Design Patterns

Last Updated : 31 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

The factory design pattern is a creational design pattern. It states the best way to create an object without telling the exact class of object that will be created. It is used when we have a super-class with multiple sub-classes and based on input, we want to return one of the sub-class.

Understanding the Factory Method in Java Design Patterns

Let’s consider the above-mentioned diagram for implementing a factory design pattern. Here is a Factory Method pattern to convert currency values between Indian Rupees (INR), US Dollars (USD), and Great British Pounds (GBP).

Step 1: Define the Product(Currency):

This is an interface or an abstract class that declares the method(s) that need to be implemented by the concrete products. In the example provided, Currency is the product interface with the method getSymbol().

Java




public interface Currency {
    public String getSymbol();
}


Step 2: Create Concrete Products (INR, USD, GBP):

These are the actual implementations of the Currency interface. Each concrete product provides its own implementation of the getSymbol() method. In the example, INR, USD, and GBP are concrete implementations.

Java




public class INR implements Currency {
    @Override public String getSymbol() { return "₹"; }
}


Java




public class GBP implements Currency {
    @Override public String getSymbol() { return "£"; }
}


Java




public class USD implements Currency {
    @Override public String getSymbol() { return "$"; }
}


Step 3: Define the Factory (CurrencyFactory):

This is an interface or an abstract class that declares the method for creating objects. In the example, CurrencyFactory is the factory interface with the method createCurrency().

Java




public interface CurrencyFactory {
    Currency createCurrency();
}


Step 4: Create Concrete Factories (INRFactory, USDFactory, GBPFactory):

These are the actual implementations of the factory interface. Each concrete factory is responsible for creating an instance of a specific concrete product. In the example, INRFactory, USDFactory, and GBPFactory are concrete factory implementations.

Java




public class INRFactory implements CurrencyFactory {
    @Override public Currency createCurrency()
    {
        return new INR();
    }
}


Java




public class USDFactory implements CurrencyFactory {
    @Override public Currency createCurrency()
    {
        return new USD();
    }
}


Java




public static class GBPFactory
        implements CurrencyFactory {
        @Override public Currency createCurrency()
        {
            return new GBP();
        }
    }


Code:

Java




import java.util.*;
 
     
public class Main {
//Currency is the product interface with method getSymbol.
    public interface Currency {
        public String getSymbol();
    }
// This interface represents the CurrencyFactory responsible for creating instances of Currency implementations.
    public interface CurrencyFactory {
         
        Currency createCurrency();
    }
// It provides an implementation for the getSymbol() method representing the Indian Rupee currency symbol.
    public static class INR implements Currency{
        @Override public String getSymbol() {
            return "₹";
        }
}
//createCurrency() method that creates and returns an instance of INR.
    public static class INRFactory
        implements CurrencyFactory {
        @Override public Currency createCurrency()
        {
            return new INR();
        }
    }
// It provides an implementation for the getSymbol() method representing the GBP currency symbol.
    public static class GBP implements Currency {
        @Override public String getSymbol() {
            return "£";
        }
    }
//createCurrency() method that creates and returns an instance of GBP.
    public static class GBPFactory
        implements CurrencyFactory {
        @Override public Currency createCurrency()
        {
            return new GBP();
        }
    }
// It provides an implementation for the getSymbol() method representing the USD
    public static class USD implements Currency {
        @Override public String getSymbol() {
            return "$";
        }
    }
//createCurrency() method that creates and returns an instance of USD.
    public static class USDFactory
        implements CurrencyFactory {
        @Override public Currency createCurrency()
        {
            return new USD();
        }
    }
     
    public static void main(String[] args) throws Exception
    {
         
        INRFactory objINRFactory = new INRFactory();
        Currency objINRCurrency = objINRFactory.createCurrency();
        
        GBPFactory objGBPFactory = new GBPFactory();
        Currency objGBPCurrency = objGBPFactory.createCurrency();
         
        USDFactory objUSDFactory = new USDFactory();
        Currency objUSDCurrency = objUSDFactory.createCurrency();
         
        System.out.println("Symbol of INR: "+objINRCurrency.getSymbol());
        System.out.println("Symbol of GBP: "+objGBPCurrency.getSymbol());
        System.out.println("Symbol of USD: "+objUSDCurrency.getSymbol());
    }
}


Output

Symbol of INR: ₹
Symbol of GBP: £
Symbol of USD: $


Below is the explanation of the above example:

  • We have defined a Currency interface with three concrete implementations (INR, USD, and GBP).
  • We also have a CurrencyFactory interface with three concrete factory implementations (INRFactory, USDFactory, and GBPFactory) responsible for creating instances of the respective currencies.
  • When we run the Main class, we get the symbols for INR, USD, and GBP as expected.
  • This demonstrates how the Factory Method pattern allows us to create objects without specifying the exact class at compile time.

When to Use the Factory Method in Java Design Patterns

This pattern takes whole and sole responsibility of the instantiation of a class from client program to the factory class. It help to provide an way to create a objects without specifying the exact class of that will be created.Some of the following point when to use Factory Design Pattern:

  • When you have different type of things to create: Imagine that you have a program that needs to create different kind of shapes, like circle, triangle and square. Factory pattern will help you to create there shapes without knowing the exact details of each of them.
  • When we want to organize how objects are made: Consider creating an object involves a bunch of steps or rules. A factory help you keep all these steps in one place, making code easier to maintain.
  • When you want to let subclass take decision for what to create: Say if you have a basic class like Currency and you want a specific subclass(like USB, GSD, INR) to decide how they’re made, a factory pattern is suitable here. It let’s each subclass have its own way of creating itself.

Important Points to Keep in Mind for the Factory Method in Java Design Patterns

  • Factory Design Pattern simplifies complex object creation processes.
  • It decouples client code from concrete implementations for flexibility.
  • Enables subclassing to create different types of objects.
  • Reduces tight coupling, allowing for easier implementation swapping.
  • Supports lazy initialization for resource-intensive objects.
  • Centralizes object configuration and rule application.
  • Facilitates unit testing and mocking of dependencies.
  • Manages object creation in inheritance hierarchies.
  • Dynamically loads and instantiates classes, useful for plugins.
  • Enforces design constraints and business rules during creation.

Advantages of the Factory Design Pattern in Java Design Patterns

  • It helps in centralizing object creation logic. This makes it easier to manage and maintain the creation process, especially in complex systems with multiple dependencies.
  • It promotes Open-Closed principle It adheres to the open-closed principle, which means that you can introduce new types of products (concrete classes) without modifying existing client code. This promotes code extensibility and maintainability.
  • Factory decouples Object Creation. It decouples the client code from the actual implementation of the objects. The client code interacts with the factory interface or class, rather than directly with the concrete classes. This reduces the dependencies between components.
  • Promotes Consistent Interfaces. It ensures that all created objects adhere to a consistent interface (the product interface or abstract class). This makes it easier for clients to work with the objects, as they can rely on a known set of methods.

Disadvantages of the Factory Design Pattern in Java Design Patterns

  • It increased complexity. As implementing the factory pattern can add complexity especially in simple scenarios where direct instantiation suffices.
  • It increased overhead as it involves creating additional classes and interfaces, potentially adding unnecessary code.
  • It leads to tight coupling, sometimes poor implementation tends to make tight dependencies between client and concrete factories, making future changes more challenging.
  • It increased maintenance overhead as managing multiple concrete classes and factories can become burdensome, especially as the hierarchy grows in complexity.

Conclusion

Factory design pattern provides a way to create objects without specifying their exact class at compile time. It involves defining an interface or abstract class for creating objects (the factory) and allowing subclasses to alter the type of objects that will be created. This pattern decouples object creation from the client code, promoting flexibility, maintainability, and scalability.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads