Java Factory Pattern example
Factory Design Pattern
The Factory Design Pattern is a creational pattern. Its main purpose is to encapsulate object creation logic that would be otherwise spread all over the application. The factory should also return always an interface to the calling client. This way one may change implementations without changing the client code, ie. the client becomes decoupled from the actual business logic implementation.
The factory pattern is also able to choose a concrete implementation to instantiate based on parameters sent by the client.
By using the factory pattern one also ensures that the created instances will be in correct and consistent state when returned to the client.
In this article we will implement a factory that will be responsible to create loggers. There will be a couple of available logger types: database and file. The factory will create an instance of the specified logger and return it to the client.
The Logger
We start by defining the Logger interface we will be producing:
package com.byteslounge.logger; public interface Logger { public void log(String message); }
Now we define the file Logger implementation:
package com.byteslounge.logger; public class FileLogger implements Logger { @Override public void log(String message) { System.out.println("Logging to file: " + message); } }
And also the database Logger implementation:
package com.byteslounge.logger; public class DatabaseLogger implements Logger { @Override public void log(String message) { System.out.println("Logging to database: " + message); } }
The Factory
Now we will define the factory that will be responsible for Logger instances creation:
package com.byteslounge.logger.factory; import com.byteslounge.logger.DatabaseLogger; import com.byteslounge.logger.FileLogger; import com.byteslounge.logger.Logger; public class LoggerFactory { private LoggerFactory() { } public static Logger getLogger(LoggerType loggerType) { Logger logger; switch (loggerType) { case DATABASE: logger = new DatabaseLogger(); break; default: logger = new FileLogger(); } return logger; } public enum LoggerType { DATABASE, FILE; } }
We defined an enum LoggerType containing the available logger types: DATABASE and FILE.
Based on the requested logger type that is passed to the factory method - getLogger() - a concrete instance will be created and returned to the client.
Testing the factory
Now we may write a simple application class that will be used to test our logger factory:
package com.byteslounge; import com.byteslounge.logger.Logger; import com.byteslounge.logger.factory.LoggerFactory; import com.byteslounge.logger.factory.LoggerFactory.LoggerType; public class Application { // Get logger of type DATABASE from logger factory private final Logger logger = LoggerFactory.getLogger(LoggerType.DATABASE); private void doSomething() { logger.log("Executing method doSomething()"); // do something } public static void main(String[] args) { Application application = new Application(); application.doSomething(); } }
When we launch our application the following output will be generated: