How to create Abstract Factory Pattern in Java

  • 03 November 2016
  • ADM

 

How to create Abstract Factory Pattern in Java - images/logos/oopjava.jpg

 

Abstract Factory pattern work as a super-factory which creates other factories. The abstract factory design pattern relies on inheritance, as the object creation is delegated to the sub-classes that implement the abstract factory method to create objects. Abstract Factory Design Pattern is basically a Factory Design Pattern for Factory Objects.

Example

A good example where the Abstract Factory Design Pattern can be used if is needed to implement an generic solution for creating a database table and stored procedure regardless the database engine.

In order to follow the Abstract Factory Design Pattern implementation, will need two interfaces to define the behaviour for the objects and one interface to define the factory object.

package com.admfactory.abstractfactory;

public interface Table {
    public boolean create();
}
package com.admfactory.abstractfactory;

public interface StoredProcedure {
    public boolean create();
}

The interface to define the abstract factory:

package com.admfactory.abstractfactory;

public interface AFactory {

    public Table getTable(DatabaseType type);
    public StoredProcedure getStoredProcedure(DatabaseType type);
}

DatabaseType.java

package com.admfactory.abstractfactory;

public enum DatabaseType {
    MySQL, MSSQL, Oracle, PostgreSQL
}

FactoryType.java

package com.admfactory.abstractfactory;

public enum FactoryType {
    Table, StoredProcedure
}

Here are all concrete classes for defining tables:

package com.admfactory.abstractfactory;

public class MSSQLTable implements Table {

    @Override
    public boolean create() {
	System.out.println("MSSQLTable::create() was called.");
	return true;
    }
}
package com.admfactory.abstractfactory;

public class MySQLTable implements Table {

    @Override
    public boolean create() {
	System.out.println("MySQLTable::create() was called.");
	return true;
    }
}
package com.admfactory.abstractfactory;

public class OracleTable implements Table {

    @Override
    public boolean create() {
	System.out.println("OracleTable::create() was called.");
	return true;
    }
}
package com.admfactory.abstractfactory;

public class PostgreSQLTable implements Table {

    @Override
    public boolean create() {
	System.out.println("PostgreSQLTable::create() was called.");
	return true;
    }
}

Similar with the tables classes, here are the stored procedure classes:

package com.admfactory.abstractfactory;

public class MSSQLStoredProcedure implements StoredProcedure {

    @Override
    public boolean create() {
	System.out.println("MSSQLStoredProcedure::create() was called.");
	return true;
    }
}
package com.admfactory.abstractfactory;

public class MySQLStoredProcedure implements StoredProcedure {

    @Override
    public boolean create() {
	System.out.println("MySQLStoredProcedure::create() was called.");
	return true;
    }
}
package com.admfactory.abstractfactory;

public class OracleStoredProcedure implements StoredProcedure {

    @Override
    public boolean create() {
	System.out.println("OracleStoredProcedure::create() was called.");
	return true;
    }
}
package com.admfactory.abstractfactory;

public class PostgreSQLStoredProcedure implements StoredProcedure {

    @Override
    public boolean create() {
	System.out.println("PostgreSQLStoredProcedure::create() was called.");
	return true;
    }
}

Here is the producer class for the factory creation:

package com.admfactory.abstractfactory;

public class FactoryProducer {

    public static AFactory getFactory(FactoryType type) {
	if (type == FactoryType.Table) {
	    return new TableFactory();
	} else if (type == FactoryType.StoredProcedure) {
	    return new StoredProcedureFactory();
	} else {
	    return null;
	}
    }
}

Last, but not the least the factory classes:

package com.admfactory.abstractfactory;

public class TableFactory implements AFactory {

    @Override
    public Table getTable(DatabaseType type) {
	if (type == DatabaseType.MySQL) {
	    return new MySQLTable();
	} else if (type == DatabaseType.MSSQL) {
	    return new MSSQLTable();
	} else if (type == DatabaseType.PostgreSQL) {
	    return new PostgreSQLTable();
	} else if (type == DatabaseType.Oracle) {
	    return new OracleTable();
	} else {
	    return null;
	}
    }

    @Override
    public StoredProcedure getStoredProcedure(DatabaseType type) {
	System.out.println("TableFactory::getStoredProcedure(DatabaseType type) not implemented.");
	return null;
    }
}
package com.admfactory.abstractfactory;

public class StoredProcedureFactory implements AFactory {

    @Override
    public Table getTable(DatabaseType type) {
	System.out.println("StoredProcedureFactory::getTable(DatabaseType type) not implemented.");
	return null;
    }

    @Override
    public StoredProcedure getStoredProcedure(DatabaseType type) {
	if (type == DatabaseType.MySQL) {
	    return new MySQLStoredProcedure();
	} else if (type == DatabaseType.MSSQL) {
	    return new MSSQLStoredProcedure();
	} else if (type == DatabaseType.PostgreSQL) {
	    return new PostgreSQLStoredProcedure();
	} else if (type == DatabaseType.Oracle) {
	    return new OracleStoredProcedure();
	} else {
	    return null;
	}
    }

}

Usage

package com.admfactory.abstractfactory;

public class AbstractFactoryExample {
    public static void main(String[] args) {
	System.out.println("Abstract Factory Design Pattern Example");
	System.out.println();

	AFactory tFactory = FactoryProducer.getFactory(FactoryType.Table);

	System.out.println("Creating tables...");
	System.out.println();
	Table table1 = tFactory.getTable(DatabaseType.MSSQL);
	table1.create();

	Table table2 = tFactory.getTable(DatabaseType.MySQL);
	table2.create();

	Table table3 = tFactory.getTable(DatabaseType.PostgreSQL);
	table3.create();

	Table table4 = tFactory.getTable(DatabaseType.Oracle);
	table4.create();
	
	StoredProcedure spE = tFactory.getStoredProcedure(DatabaseType.MSSQL);

	System.out.println();
	AFactory sFactory = FactoryProducer.getFactory(FactoryType.StoredProcedure);

	System.out.println("Creating stored procedures...");
	System.out.println();
	StoredProcedure sp1 = sFactory.getStoredProcedure(DatabaseType.MSSQL);
	sp1.create();

	StoredProcedure sp2 = sFactory.getStoredProcedure(DatabaseType.MySQL);
	sp2.create();

	StoredProcedure sp3 = sFactory.getStoredProcedure(DatabaseType.PostgreSQL);
	sp3.create();

	StoredProcedure sp4 = sFactory.getStoredProcedure(DatabaseType.Oracle);
	sp4.create();
	
	Table tbE = sFactory.getTable(DatabaseType.MSSQL);
    }

}

Output

Abstract Factory Design Pattern Example

Creating tables...

MSSQLTable::create() was called.
MySQLTable::create() was called.
PostgreSQLTable::create() was called.
OracleTable::create() was called.
TableFactory::getStoredProcedure(DatabaseType type) not implemented.

Creating stored procedures...

MSSQLStoredProcedure::create() was called.
MySQLStoredProcedure::create() was called.
PostgreSQLStoredProcedure::create() was called.
OracleStoredProcedure::create() was called.
StoredProcedureFactory::getTable(DatabaseType type) not implemented.