Introduction

Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. This pattern is almost similar to Factory Pattern, is considered as another layer of abstraction over Factory pattern. Abstract Factory patterns work around a super-factory which creates other factories. It relies on object composition: object creation is implemented in methods exposed in the factory interface. The intent of Abstract Factory is to create families of related objects without having to depend on their concrete classes.

This pattern provides us a framework that allows us to create objects that follow a general pattern. So at runtime, abstract factory is coupled with any desired concrete factory which can create objects of desired type. The Abstract Factory defines a Factory Method per product. Each Factory Method encapsulates the new operator and the concrete, platform-specific, product classes. Each “platform” is then modeled with a Factory derived class.

Implementation

The pattern basically works as shown below, in the UML diagram.

Example

// Two products
abstract class AbstractProductA{
  public abstract void operationA1();
  public abstract void operationA2();
}

abstract class AbstractProductB{
  public abstract void operationB1();
  public abstract void operationB2();
}

// Concrete implementation
class ProductA1 extends AbstractProductA{
  ProductA1(String arg){
    System.out.println("Hello "+arg);
  } 
  
  // Implement the code here
  public void operationA1() { };
  public void operationA2() { };
}

class ProductA2 extends AbstractProductA{
  ProductA2(String arg){
    System.out.println("Hello "+arg);
  } 
  
  // Implement the code here
  public void operationA1() { };
  public void operationA2() { };
}


class ProductB1 extends AbstractProductB{
  ProductB1(String arg){
    System.out.println("Hello "+arg);
  } 
  
  // Implement the code here
  public void operationB1() { };
  public void operationB2() { };
}

class ProductB2 extends AbstractProductB{
  ProductB2(String arg){
    System.out.println("Hello "+arg);
  } 
  
  // Implement the code here
  public void operationB1() { };
  public void operationB2() { };
}

// Defines list of product
abstract class AbstractFactory{
  abstract AbstractProductA createProductA();
  abstract AbstractProductB createProductB();
}

class ConcreteFactory1 extends AbstractFactory{

  AbstractProductA createProductA(){
    return new ProductA1("ProductA1");
  }

  AbstractProductB createProductB(){
    return new ProductB1("ProductB1");
  }
}

class ConcreteFactory2 extends AbstractFactory{
  AbstractProductA createProductA(){
    return new ProductA2("ProductA2");
  }
  AbstractProductB createProductB(){
    return new ProductB2("ProductB2");
  }
}

// Factory creator
class FactoryMaker{
  private static AbstractFactory pf=null;
  
  static AbstractFactory getFactory(String choice){
    if(choice.equals("a")){
      pf=new ConcreteFactory1();
    }else if(choice.equals("b")){
        pf=new ConcreteFactory2();
      } return pf;
  }
}

// Client
public class Client{
  public static void main(String args[]){
    AbstractFactory pf	= FactoryMaker.getFactory("a");
    AbstractProductA p	= pf.createProductA();
  }
}