Abstract Factory Design Pattern In Java

The Abstract Factory design pattern is a creational design pattern that contains a factory class which creates other factories. It is typically called the Factory of factories. There is an abstract Factory class that other factories inherit in order to implement their own factory method. 

A real world example of this would be a Database or Cache implementation. Let’s say you need to make database updates but need to update a SQL Server, MongoDB, and an Oracle database. These would use similar operations but would require a different implantation in order to connect, update, add and delete data from the database. Abstract Factory would come in handy here because you could have separate factories for a relational and non-relational database.

We are going to implement an example of the Abstract Factory Pattern with a Database implementation in Java. We will create an abstract class DatabaseFactory and 2 concrete classes RelationalDBFactory and NonRelationalDBFactory. The DatabaseFactory class will have a static method getFactory()that returns DatabaseFactory. The concrete classes will return a Database object depending on the type. 


1.  Create the abstract class DatabaseFactory. This contains a static method getFactory(String factory) that returns the correct factory object based on the parameter. getDatabase(String database) is an abstract method that the sub-classes will override.

public abstract class DatabaseFactory {

    /**
     * Returns the correct Factory object based on the type.
     * 
     * @param factory
     * @return
     */
    public static DatabaseFactory getFactory(String factory) {
        switch (factory) {
            case "Relational":
                return new RelationalDBFactory();
            case "NonRelational":
                return new NonRelationalDBFactory();
            default:
                return null;
        }
    }

    public abstract Database getDatabase(String database);
}

2. Create the sub-classes RelationalDBFactory and NonRelationalDBFactory. They contain their own version of getDatabase()  that will return a database object such as Mongodb, NoSQL, SQLServer, and MySQL.

public class NonRelationalDBFactory extends DatabaseFactory {

    /**
     * Returns a Database object of either Mongodb or NoSQL which are Non-relational databases.
     * @param database
     * @return
     */
    @Override
    public Database getDatabase(String database) {
        switch (database){
            case "Mongodb":
                return new MongoDB();
            case "NoSQL":
                return new NoSQL();
            default:
                return null;
        }
    }
}
public class RelationalDBFactory extends DatabaseFactory {

    /**
     *  Returns a Database object of either SQLServer or MySQL which are Relational databases.
     *
     * @param database
     * @return
     */
    @Override
    public Database getDatabase(String database) {
        switch (database){
            case "SQLServer":
                return new SQLServer();
            case "MySQL":
                return new MySQL();
            default:
                return null;
        }
    }
}


3. Create a Database interface and 4 sub-classes that implement their own connect(), add(), update(), and delete() methods. We don’t care if they are Relational or Non-relational at this point since the factory classes handle that logic.

public interface Database {
    void connect();
    void add();
    void update();
    void delete();
}
public class MongoDB implements Database {
    @Override
    public void connect() {
        System.out.println("Connected to MongoDB Non-Relational Database!");
    }

    @Override
    public void add() {
        System.out.println("Added data to MongoDB Non-Relational Database!");
    }

    @Override
    public void update() {
        System.out.println("Updated data in MongoDB Non-Relational Database!");
    }

    @Override
    public void delete() {
        System.out.println("Deleted data from MongoDB Non-Relational Database!");
    }
}
public class MySQL implements Database {
    @Override
    public void connect() {
        System.out.println("Connected to MySQL Relational Database!");
    }

    @Override
    public void add() {
        System.out.println("Added data to MySQL Relational Database!");
    }

    @Override
    public void update() {
        System.out.println("Updated data in MySQL Relational Database!");
    }

    @Override
    public void delete() {
        System.out.println("Deleted data from MySQL Relational Database!");
    }
}
public class NoSQL implements Database {
    @Override
    public void connect() {
        System.out.println("Connected to NoSQL Non-Relational Database!");
    }

    @Override
    public void add() {
        System.out.println("Added data to NoSQL Non-Relational Database!");
    }

    @Override
    public void update() {
        System.out.println("Updated data in NoSQL Non-Relational Database!");
    }

    @Override
    public void delete() {
        System.out.println("Deleted data from NoSQL Non-Relational Database!");
    }
}
public class SQLServer implements Database {
    @Override
    public void connect() {
        System.out.println("Connected to SQL Server Database");
    }

    @Override
    public void add() {
        System.out.println("Added data to SQL Server Database!");
    }

    @Override
    public void update() {
        System.out.println("Updated data for SQL Server Database!");
    }

    @Override
    public void delete() {
        System.out.println("Deleted data from SQL Server Database!");
    }
}


4. Now we can create the client class and use our factory implementation. We call the static method getFactory(“Relational”) to retrieve our DatabaseFactory method. Then we get the database object that we want to use, SQLServer and MySQL. We then do the same thing for NonRelational.

public class AbstractFactoryClient {
    public static void main(String[] args) {
        //Returns a Relational DatabaseFactory object.
        DatabaseFactory relationalFactory = DatabaseFactory.getFactory("Relational");

        //Returns a SQLServer Database object.
        Database sqlServer = relationalFactory.getDatabase("SQLServer");
        sqlServer.connect();
        sqlServer.add();
        sqlServer.update();
        sqlServer.delete();
        System.out.println();

        //Returns a SQLServer Database object.
        Database mySql = relationalFactory.getDatabase("MySQL");
        mySql.connect();
        mySql.add();
        mySql.update();
        mySql.delete();
        System.out.println();

        //Returns a Non-Relational DatabaseFactory object.
        DatabaseFactory nonRelationalFactory = DatabaseFactory.getFactory("NonRelational");

        //Returns a Mongodb Database object.
        Database mongoDb = nonRelationalFactory.getDatabase("Mongodb");
        mongoDb.connect();
        mongoDb.add();
        mongoDb.update();
        mongoDb.delete();
        System.out.println();

        //Returns a NoSQL Database object.
        Database noSql = nonRelationalFactory.getDatabase("NoSQL");
        noSql.connect();
        noSql.add();
        noSql.update();
        noSql.delete();
        System.out.println();
    }
}
Connected to SQL Server Database
Added data to SQL Server Database!
Updated data for SQL Server Database!
Deleted data from SQL Server Database!

Connected to MySQL Relational Database!
Added data to MySQL Relational Database!
Updated data in MySQL Relational Database!
Deleted data from MySQL Relational Database!

Connected to MongoDB Non-Relational Database!
Added data to MongoDB Non-Relational Database!
Updated data in MongoDB Non-Relational Database!
Deleted data from MongoDB Non-Relational Database!

Connected to NoSQL Non-Relational Database!
Added data to NoSQL Non-Relational Database!
Updated data in NoSQL Non-Relational Database!
Deleted data from NoSQL Non-Relational Database!


Process finished with exit code 0