Abstract Factory Design Pattern in Java

Introduction

Abstract Factory pattern is one of the most used design pattern in Java. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object. Abstract Factory patterns works around a parent-factory which creates other factories. This factory is also called as Factory of factories. In Abstract Factory pattern an interface is responsible for creating a factory of related objects, without explicitly specifying their classes. Each generated factory can give the objects as per the Factory pattern.

Implementation

We will create Building and PaintCompany interfaces and concrete classes implementing these interfaces. We will also create an abstract factory class AbstractFactory later. Factory classes BuildingFactory and PaintFactory are defined where each factory extends AbstractFactory. A factory creator or generator class FactoryProducer is created. The demo class AbstractFactoryPatternDemo uses FactoryProducer to get a AbstractFactory object. It will pass information (Home / House / Hut for Building) to AbstractFactory to get the type of object it needs. It also passes information (Asian / Berger / Nerolac for Paint Company) to AbstractFactory to get the type of object it needs.

Class Diagram

abstract factory pattern in Java

The following steps illustrate how to create abstract factory pattern

Step 1. Create a Building interface. This interface has only one method build() which will be implemented by different classes to build different kind of buildings.

package com.roytuts.designpattern.factory;
public interface Building {
  void build();
}

Step 2. Create concrete classes to implement the Building interface.

The below class builds a Home.

package com.roytuts.designpattern.factory;
public class Home implements Building {
  @Override
  public void build() {
    System.out.println("Building Home");
  }
}

The below class builds a House.

package com.roytuts.designpattern.factory;
public class House implements Building {
  @Override
  public void build() {
    System.out.println("Building House");
  }
}

The below class builds a Hut.

package com.roytuts.designpattern.factory;
public class Hut implements Building {
  @Override
  public void build() {
    System.out.println("Building Hut");
  }
}

Step 3. Create a PaintComapny interface. This interface has only one method paint() which will be implemented by different classes to paint from the different paint company.

package com.roytuts.designpattern.abstractfactory;
public interface PaintCompany {
  void paint();
}

Step 4. Create concrete classes to implement the PaintComapny interface.

The below class paints from Asian paint company.

package com.roytuts.designpattern.abstractfactory;
public class AsianPaint implements PaintCompany {
  @Override
  public void paint() {
    System.out.println("Paint with Asian Paints.");
  }
}

The below class paints from Berger paint company.

package com.roytuts.designpattern.abstractfactory;
public class BergerPaint implements PaintCompany {
  @Override
  public void paint() {
    System.out.println("Paint with Berger Paints");
  }
}

The below class paints from Nerolac paint company.

package com.roytuts.designpattern.abstractfactory;
public class NerolacPaint implements PaintCompany {
  @Override
  public void paint() {
    System.out.println("Paint with Nerolac paints");
  }
}

Step 5. Create an Abstract class to get factories for Building and PaintComapny Objects.

package com.roytuts.designpattern.abstractfactory;
public abstract class AbstractFactory {
  abstract Building getBuilding(String buildingType);
  abstract PaintCompany getPaintCompany(String paintType);
}

Step 6. Create Factory classes extending AbstractFactory to generate object of concrete class based on given information.

The below class is for BuildingFactory.

package com.roytuts.designpattern.abstractfactory;
public class BuildingFactory extends AbstractFactory {
  @Override
  public Building getBuilding(String buildingType) {
    if (buildingType != null) {
      if ("HOME".equalsIgnoreCase(buildingType)) {
        return new Home();
      }
      if ("HOUSE".equalsIgnoreCase(buildingType)) {
        return new House();
      }
      if ("HUT".equalsIgnoreCase(buildingType)) {
        return new Hut();
      }
    }
    return null;
  }
  @Override
  PaintCompany getPaintCompany(String paintType) {
    return null;
  }
}

The below class is for PaintFactory.

package com.roytuts.designpattern.abstractfactory;
public class PaintFactory extends AbstractFactory {
  @Override
  Building getBuilding(String buildingType) {
    return null;
  }
  @Override
  PaintCompany getPaintCompany(String paintType) {
    if (paintType != null) {
      if ("Asian".equalsIgnoreCase(paintType)) {
        return new AsianPaint();
      }
      if ("Berger".equalsIgnoreCase(paintType)) {
        return new BergerPaint();
      }
      if ("Nerolac".equalsIgnoreCase(paintType)) {
        return new NerolacPaint();
      }
    }
    return null;
  }
}

Step 7. Create a Factory generator or producer class to get factories by passing an information such as Building type or Paint company

package com.roytuts.designpattern.abstractfactory;
public class FactoryProducer {
  public static AbstractFactory getFactory(String choice) {
    if (choice != null) {
      if ("Building".equalsIgnoreCase(choice)) {
        return new BuildingFactory();
      }
      if ("Paint".equalsIgnoreCase(choice)) {
        return new PaintFactory();
      }
    }
    return null;
  }
}

Step 8. Use the FactoryProducer to get AbstractFactory in order to get factories of concrete classes by passing information such as type.

package com.roytuts.designpattern.abstractfactory;
public class AbstractFactoryPatternDemo {
  /**
   * @param args
   */
  public static void main(String[] args) {
    AbstractFactory buildingFactory = FactoryProducer.getFactory("Building");
    Building building1 = buildingFactory.getBuilding("Home");
    building1.build();
    Building building2 = buildingFactory.getBuilding("House");
    building2.build();
    Building building3 = buildingFactory.getBuilding("Hut");
    building3.build();
    AbstractFactory paintFactory = FactoryProducer.getFactory("Paint");
    PaintCompany paintCompany1 = paintFactory.getPaintCompany("Asian");
    paintCompany1.paint();
    PaintCompany paintCompany2 = paintFactory.getPaintCompany("Berger");
    paintCompany2.paint();
    PaintCompany paintCompany3 = paintFactory.getPaintCompany("Nerolac");
    paintCompany3.paint();
  }
}

Step 9. Run the class AbstractFactoryPatternDemo. Verify the output

Building Home
Building House
Building Hut
Paint with Asian Paints.
Paint with Berger Paints
Paint with Nerolac paints

That’s all. Thank you for your reading.
 
 
 

1 thought on “Abstract Factory Design Pattern in Java

  1. Instead of giving the AbstractFactory we can give 2 interfaces also, why to its required to forcefully override methods and return null, its violated SOLID principal Interface Segregation Principal.

Leave a Reply

Your email address will not be published. Required fields are marked *