Java Abstract Factory Pattern example

29 January 2014
By Gonçalo Marques
In this tutorial we will see how to implement the Abstract Factory design pattern in Java.

Abstract Factory Design Pattern

The Abstract Factory Design Pattern is a creational pattern. It's main purpose is to provide a way to create a related set of concrete objects without knowing about their concrete implementation. Actually the application should also be implemented against an abstract factory interface without even knowing about the factory implementation.

Usually the concrete factory implementation is provided to the application at runtime. Since the abstract factory should always provide (or build) objects in the form of interfaces, the application will become completely decoupled from both the factory and the business objects concrete implementation.

One may notice that, since the concrete factory implementation is provided to the application at runtime, we are actually injecting the factory as a dependency into the application. The abstract factory pattern is very common in applications that rely in the Dependency Injection paradigm.

In this article we will build a simple example consisting on an abstract factory that will create illustrative connections to a database.

The database connection

Our abstract factory will be able to produce database connections. Let's define the connection interface:

Connection interface

package com.byteslounge.db.connection;

public interface Connection {

  public void connect();

}

And now a couple of illustrative concrete implementations:

MySql connection implementation

package com.byteslounge.db.connection;

public class MySqlConnection implements Connection {

  @Override
  public void connect() {
    System.out.println("Connecting to MySQL...");
  }

}

PostgreSql connection implementation

package com.byteslounge.db.connection;

public class PostgreSqlConnection implements Connection {

  @Override
  public void connect() {
    System.out.println("Connecting to PostgreSQL...");
  }

}

The abstract factory

Now let's define the abstract connection factory interface:

Abstract connection factory interface

package com.byteslounge.db.connection.factory;

import com.byteslounge.db.connection.Connection;

public interface ConnectionFactory {

  Connection getConnection();

}

And now a couple of concrete factory implementations, one for each of the connection types we are building (MySQL and PostgreSQL):

MySQL connection factory implementation

package com.byteslounge.db.connection.factory;

import com.byteslounge.db.connection.Connection;
import com.byteslounge.db.connection.MySqlConnection;

public class MySqlConnectionFactory implements ConnectionFactory {

  @Override
  public Connection getConnection() {
    return new MySqlConnection();
  }

}

PostgreSQL connection factory implementation

package com.byteslounge.db.connection.factory;

import com.byteslounge.db.connection.Connection;
import com.byteslounge.db.connection.PostgreSqlConnection;

public class PostgreSqlConnectionFactory implements ConnectionFactory {

  @Override
  public Connection getConnection() {
    return new PostgreSqlConnection();
  }

}

Now that we have everything set, we may use the abstract factory to create connections within the application.

A sample application

We may now define an illustrative application that will use an injected factory implementation:

Sample application

package com.byteslounge.application;

import com.byteslounge.db.connection.Connection;
import com.byteslounge.db.connection.factory.ConnectionFactory;

public class Application {

  private final ConnectionFactory connectionFactory;

  public Application(ConnectionFactory connectionFactory) {
    this.connectionFactory = connectionFactory;
  }

  public void start() {
    Connection connection = connectionFactory.getConnection();
    connection.connect();
    // proceed with application execution...
  }

}

As we can see the application is completely decoupled from both the connection factory and the database connections concrete implementations. The application only knows that it will receive some factory that will produce database connections.

Testing

Finally we create a runnable class in order to test the application:

Main.java

package com.byteslounge;

import com.byteslounge.application.Application;
import com.byteslounge.db.connection.factory.ConnectionFactory;
import com.byteslounge.db.connection.factory.MySqlConnectionFactory;
import com.byteslounge.db.connection.factory.PostgreSqlConnectionFactory;

public class Main {

  public static void main(String[] args) {

    // We should fetch the database type from an
    // external resource (ex: configuration file).
    // In order to keep this example simple we will
    // use a private static method and an Enum
    DatabaseType databaseType = DatabaseType.MYSQL;
    ConnectionFactory connectionFactory = 
             getConnectionFactory(databaseType);

    Application application = new Application(connectionFactory);
    application.start();
  }

  private static ConnectionFactory getConnectionFactory(
      DatabaseType databaseType) {
    switch (databaseType) {
    case MYSQL:
      return new MySqlConnectionFactory();
    default:
      return new PostgreSqlConnectionFactory();
    }
  }

  private enum DatabaseType {
    MYSQL, POSTGRE;
  }

}

The database type could be configured in an external resource, like a properties file. The client would then create a concrete factory implementation from the external configuration file and inject it into the application.

To keep this example simple we used a static method that creates the concrete factory implementation based on an Enum.

Since we are creating a MySQL factory implementation and passing it into the application, the following output will be generated when the sample is executed:

Connecting to MySQL...

Encapsulation

A final note about encapsulation: In this example we defined an abstract factory that produces only database connections. We could have defined our factory at a higher level (like a database driver) and use it to produce all sorts of low level database artifacts, like connections, transactions, prepared statements among others.

The concrete factories would then produce the database artifacts for each distinct database type they implement. By using this paradigm we are clearly also providing an higher level of encapsulation, since our abstract factory (and its concrete implementations) would encapsulate all the the database related artifacts production.

Download source code from this article

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with several years of experience in software development and architecture definition. During this period his main focus was delivering software solutions in banking, telecommunications and governmental areas. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

GitHub profile: https://github.com/gonmarques

He is also the author of the WiFi File Browser Android application: