The Factory Pattern in Java

Contents

Introduction to the Factory Pattern

Design pattern in a simple meaning, is a way to design reusable object-oriented code. We can think of ways to design our classes, interfaces, enums and their members so that the code is reusable but flexible.

There are 23 most important design patterns, pioneered by the book Design Patterns: Elements of Reusable Object-Oriented Software, written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides or Gang of Four for short. We will cover these design pattern one by one.

The factory pattern is used when we have a base class and lots of subclasses and we have to create an object from the subclasses based on some conditions. By GoF definition, the pattern defines an interface for creating an object, but let the subclass of the class decide which to instantiate.

Implementation of the Factory Pattern

Say we have an Animal class with two subclasses Cat and Dog, the Animal.java:

public abstract class Animal {
  abstract void speak();
}
class Dog extends Animal{
  void speak() {
    System.out.println("growl");
  }
}
class Cat extends Animal{
  void speak() {
    System.out.println("meow");
  }
}

And the Factory.java:

public class Factory {
  public Factory(){}
  Animal createAnimal(String type){
    Animal animal = null;
    if ("cat".equalsIgnoreCase(type))
      animal = new Cat();
    else if ("dog".equalsIgnoreCase(type)){
      animal = new Dog();
    }
    return animal;
  }
}

So based on the String type passed to the createAnimal() method that the factory will create a Dog object or a Cat object. Finally in Test.java:

public class Test {
  public static void main(String[] args){
    //create the factory
    Factory factory = new Factory();
    //create Cat object
    Animal cat = factory.createAnimal("cat");
    cat.speak();
    //create Dog object
    Animal dog = factory.createAnimal("dog");
    dog.speak();
  }
}

Run the code and we have the output:

meow
growl

The Abstract Factory Design Pattern

The Abstract Factory is based on the Factory pattern, with one level higher of abstraction.

We will reuse the Animal.java from the previous example:

public abstract class Animal {
  abstract void speak();
}
class Dog extends Animal{
  void speak() {
    System.out.println("growl");
  }
}
class Cat extends Animal{
  void speak() {
    System.out.println("meow");
  }
}

Now we create a AnimalFactory interface in src folder, it is very simple:

public interface AnimalFactory {
  Animal createAnimal();
}

But instead of building a Factory class for both Dog and Cat classes, we create a Factory for each class. Also in the AnimalFactory.java:

class DogFactory implements AnimalFactory{
  public Dog createAnimal() {
    return new Dog();
  }
}
class CatFactory implements AnimalFactory{
  public Cat createAnimal() {
    return new Cat();
  }
}

Finally we create a Factory class (also in AnimalFactory.java for simplicity) , this class will create the DogFactory and CatFactory based on the String type passed to it:

class Factory{
  public AnimalFactory createFactory(String type){
    AnimalFactory af = null;
    if ("cat".equalsIgnoreCase(type))
      af = new CatFactory();
    else if ("dog".equalsIgnoreCase(type)){
      af = new DogFactory();
    }
    return af;
  }
}

This is the main difference between Abstract Factory pattern and Factory pattern. The Abstract Factory pattern creates a factory of other factories, not a factory of objects. Now in Test.java:

public class Test {
  public static void main(String[] args){
    //create the abstract factory
    Factory fa = new Factory();
    //create Cat factory
    AnimalFactory cFac = fa.createFactory("cat");
    //create Cat object from factory
    Cat cat = (Cat) cFac.createAnimal();
    cat.speak();
    //create Dog factory
    AnimalFactory dFac = fa.createFactory("dog");
    //create Dog object from factory
    Dog dog = (Dog) dFac.createAnimal();
    dog.speak();
  }
}

Run the code and we have the output:

meow
growl

As we can see, the Abstract Factory pattern is even better than the Factory pattern. Whenever we want to change something with each subclass, we will go to the subclass’s Factory and change it. The Abstract Factory and thus other subclass’s Factory will work as normal.

The Abstract Factory and thus other subclass’s Factory will work as normal.

We use the Abstract Factory when we needs to work with various families of related classes, but we don’t want it to depend on the concrete classes. They might be unknown until we create them, and we simply want to allow for future extensibility.

Leave a Reply