Factory pattern deals with creating objects of a single type. Define an interface or abstract class for creating an object but let the Subclass decide which class to instantiate.

Why Factory Pattern?
Factory pattern was introduced to hide the Complexity of Object creation and to delegate much of Object creation details to Separate Class(Factory Class – LoggerFactory.java) to avoid unnecessary boiler plate code.

When to use factory Pattern?

  1. Instead of using the new operator or a constructor directly, you use a factory method or a factory class that returns an object of the desired type. The factory method or class can handle the logic of choosing the right subclass, setting the initial state, or applying any dependencies or configurations to the object. This way, you can abstract the creation process and make your code more flexible and modular.
  2. Use factory pattern when We don’t know the exact class of object that will be created at runtime.
  3. To promote loose coupling between classes.
  4. It encapsulates the object creation process which makes the creation process without affecting the rest of the code

How it is implemented?

  1. You define an interface or an abstract class that represents the type of objects you want to create.
  2. Implement one or more subclasses that inherit from it. Each subclass represents a specific implementation or variation of the object.
  3. Create a factory method or a factory class that takes some parameters or input and returns an object of the interface or abstract class type.
  4. The factory method or class decides which subclass to instantiate based on the parameters or input, and returns it as the output.
  5. FactoryClass (LoggerFactory.java) with static factory method decides the objects without exposing the instantiation logic to the Client
  6. Class with main() method starts the whole process

Logger.java

public interface Logger {
    public void log();
}

ConsoleLogger.java

public class ConsoleLogger implements Logger {
    @Override
    public void log() {
        System.out.println("Logging to Console System.. . .");
    }
}

DatabaseLogger.java

public class DatabaseLogger implements Logger {
    @Override
    public void log() {
        System.out.println("Logging to Console System.. . .");
    }
}

FileLogger.java

public class FileLogger implements Logger {
    @Override
    public void log() {
        System.out.println("Logging to txt File... .");
    }
}

LoggerFactory.java

public class LoggerFactory {
    public enum LoggerType {
        DATABASE, FILE, CONSOLE;
    }

    private LoggerFactory() {
    }

    public static Logger getLogger(LoggerType loggerType) {
        Logger logger;

        switch (loggerType) {
            case DATABASE:
                logger = new DatabaseLogger();
                break;
            case CONSOLE:
                logger = new ConsoleLogger();
                break;
            case FILE:
                logger = new ConsoleLogger();
                break;
            default:
                logger = new FileLogger();
        }
        return logger;
    }
}

Client.java

public class Client {
    public static void main(String[] args) {
        Logger objLogger = LoggerFactory.getLogger(LoggerFactory.LoggerType.CONSOLE);
        objLogger.log();
    }
}

Comments are closed.