The factory design pattern

Sumonta Saha Mridul
Bootcamp
Published in
7 min readApr 2, 2023

--

What is Factory Design Pattern?

A Factory Pattern or Factory Method Pattern says that just define an interface or abstract class for creating an object but let the subclasses decide which class to instantiate. In other words, subclasses are responsible to create the instance of the class.

Advantage of Factory Design Pattern

  1. Encapsulation: The Factory Method pattern encapsulates the creation of objects, which helps to decouple the client code from the objects it needs to create. This makes it easier to modify or extend the creation process without affecting the client code.
  2. Flexibility: The Factory Method pattern makes it easy to introduce new types of objects into the system without requiring modifications to existing code. This is especially useful in situations where the types of objects needed are not known until runtime.
  3. Reusability: By centralizing object creation in a Factory class or interface, it is possible to reuse the code for object creation across multiple parts of an application.
  4. Testability: The Factory Method pattern makes it easier to test the creation of objects, as it is possible to replace the Factory implementation with a mock object for testing purposes.
  5. Maintenance: By using a Factory Method pattern, it is easier to maintain code over time, as changes to the implementation of object creation can be made in a single location rather than scattered throughout the codebase.

Let’s Understand Factory Method with example!

Let’s say we’re building a game that has different types of characters, such as warriors, wizards, and archers. Each of these characters has a specific set of abilities and attacks.

Let’s see how the code structure looks like without implementing factory pattern.

public class Warrior{
@Override
public void attack() {
System.out.println("Warrior attacks with a sword!");
}

@Override
public void defend() {
System.out.println("Warrior defends with a shield!");
}
}
public class Wizard{
@Override
public void attack() {
System.out.println("Wizard attacks with magic!");
}

@Override
public void defend() {
System.out.println("Wizard defends with a spell!");
}
}
public class Archer{
@Override
public void attack() {
System.out.println("Archer attacks with a bow!");
}

@Override
public void defend() {
System.out.println("Archer defends with a dodge!");
}
}
public class Game {
public static void main(String[] args) {
// Create a Warrior character
Character warrior = new Warrior();
warrior.attack();
warrior.defend();

// Create a Wizard character
Character wizard = new Wizard();
wizard.attack();
wizard.defend();

// Create an Archer character
Character archer = new Archer();
archer.attack();
archer.defend();

// do something with the characters ...
}
}

In this version of the code, we manually create each type of character object (Warrior, Wizard, and Archer) and call their respective attack() and defend() methods directly. This approach can work for small projects with a limited number of objects, but it can become unwieldy and difficult to maintain as the number of objects and their associated logic increases.

What’s the problem in this code design?

The Game class needs to be modified each time a new character type is added, which can lead to maintenance problems, as the class becomes more complex and harder to maintain. For instance, if a new character type “Knight” is added to the game, we would need to modify the Game class to add a new switch case for “Knight” and implement the logic for creating a new Knight object.

Let’s see how to implement the same code using factory method!

How interface helps!

First, we’ll define an interface called Character that represents a generic character in the game:

public interface Character {
void attack();
void defend();
}

Next, we’ll create concrete classes that implement the Character interface. Here's an example of a Warrior class:

Warrior Game Character
public class Warrior implements Character {
@Override
public void attack() {
System.out.println("Warrior attacks with a sword!");
}

@Override
public void defend() {
System.out.println("Warrior defends with a shield!");
}
}

Similarly, we’ll create Wizard and Archer classes that implement the Character interface.

Wizard Game Character
public class Wizard implements Character {
@Override
public void attack() {
System.out.println("Wizard attacks with magic!");
}

@Override
public void defend() {
System.out.println("Wizard defends with a spell!");
}
}
Archer Game Character
public class Archer implements Character {
@Override
public void attack() {
System.out.println("Archer attacks with a bow!");
}

@Override
public void defend() {
System.out.println("Archer defends with a dodge!");
}
}

Next, we’ll define an abstract class called CharacterFactory that defines a factory method for creating characters:

public abstract class CharacterFactory {
public abstract Character createCharacter();
}

Notice that the createCharacter() method is abstract, which means that each subclass of CharacterFactory will have to provide its own implementation of this method.

Now, we can create concrete classes that extend CharacterFactory and implement the createCharacter() method to return a specific type of character. Here's an example of a WarriorFactory:

public class WarriorFactory extends CharacterFactory {
@Override
public Character createCharacter() {
return new Warrior();
}
}

Similarly, we’ll create WizardFactory and ArcherFactory classes that extend CharacterFactory and implement the createCharacter() method to return a Wizard or Archer, respectively.

Finally, we can use the CharacterFactory and its subclasses to create new characters in our Game class:

public class Game{
public static void main(String[] args) {
CharacterFactory factory = new WarriorFactory();
Character character = factory.createCharacter();
character.attack();
character.defend();
}
}

In this example, we have three classes that implement the Character interface: Warrior, Wizard, and Archer. We also have three factory classes: WarriorFactory, WizardFactory, and ArcherFactory, each of which creates the appropriate type of Character object.

In the Game class, we create a factory object (CharacterFactory) and then use it to create a Character object (character). We can then use the attack and defend methods on the character object without needing to know the exact class of object that was created.

The advantage of using the Factory Method pattern is that it allows us to create objects without tightly coupling our code to specific classes. This makes our code more flexible and easier to maintain, since we can easily swap out different implementations of Character without having to modify the rest of our code.

Now let’s see the real magic.

Ninja Game Character

Let’s say we want to add a new character type to our game, such as a “Ninja” character.

If we use the Factory Method design pattern, we can easily add a new character type by creating a new factory class for that type, without modifying the Game class:

public class Ninja implements Character {
@Override
public void attack() {
System.out.println("Wizard attacks with magic!");
}

@Override
public void defend() {
System.out.println("Wizard defends with a spell!");
}
}

public class NinjaFactory extends CharacterFactory {
@Override
public Character createCharacter() {
return new Ninja();
}
}
public class Game {
public static void main(String[] args) {
CharacterFactory factory = new NinjaFactory();
Character ninja = factory.createCharacter();
ninja.attack();
ninja.defend();
}
}

As we can see, we simply create a new NinjaFactory class that extends the CharacterFactory abstract class and implements the createCharacter method to return a new Ninja object. Then, in the Game class, we use the NinjaFactory to create a new Ninja object without directly referencing the Ninja class.

This way, we can easily add new character types to our game by creating new factory classes for them, without modifying the existing game logic in the Game class. This makes our code more modular and flexible, and easier to maintain and extend in the future.

In conclusion, the factory method design pattern is a creational pattern that provides a way to create objects without specifying the exact class of object that will be created. It encapsulates object creation logic in a separate class, making the code more maintainable and flexible. In the example of a game with different types of characters, the factory method pattern allowed us to easily add new characters without changing the existing code. This makes the code more scalable and easier to maintain. Overall, the factory method pattern is a powerful tool in software design that can simplify complex object creation scenarios.

--

--

Strategic thinker with a passion😍 for Software Engineering💻 and a creative Photographer📸 https://sumonta056.github.io/