informa
4 MIN READ
Featured Blog

OOPsie Patterns: The Factory Method Pattern

We learn one of the cleanest ways to create objects using a design pattern with the Factory Method pattern.

Pattern Name: Factory Method pattern
Type: Creational

The factory method pattern is an incredibly useful pattern that takes polymorphism to another level.  Remember, polymorphism is the practice of creating inherited code that gets masked as it's parent object.

The Pattern

The primary purpose of the factory method pattern is to return a newly created object without specifically calling the constructor of class you want to create outside of the factory.  Essentially, the factory has a method that typically harbors a switch...case statement based on some passed in parameter (usually some kind of type) and returns an object based on what was passed in.  Let's look at a game example:

Red Dead Redemption

In Red Dead Redemption (RDR), the player is put into a western-themed world complete with frontier style battles and animals galore.  We are going to look at three different animal types found in RDR as the basis for our factory method pattern example.

Here is an example program showing an implementation of the factory method pattern:

interface IAnimal
{
    String makeNoise();
}

public class Chicken : IAnimal
{
    public Chicken()
    {

    }

    public String makeNoise()
    {
        return "Cluck, cluck!";
    }
}

public class Horse : IAnimal
{
    public Horse()
    {

    }

    public String makeNoise()
    {
        return "Neigh!";
    }
}

public class Snake : IAnimal
{
    public Snake()
    {

    }

    public String makeNoise()
    {
        return "Hissss!";
    }
}

public class AnimalFactory
{
    public enum Species
    {
        Chicken,
        Horse,
        Snake
    }

    public static IAnimal createAnimal(Species animalType)
    {
        switch(animalType)
        {
            case Species.Chicken:
                return new Chicken();
            case Species.Horse:
                return new Horse();
            case Species.Snake:
                return new Snake();
        }

        // Typically we would throw some error here
        return null;
    }
}

 public class RDRGame
{
    static void Main(String[] args)
    {
        Console.WriteLine(AnimalFactory.createAnimal(Species.Horse).makeNoise());
        Console.WriteLine(AnimalFactory.createAnimal(Species.Chicken).makeNoise());
        Console.WriteLine(AnimalFactory.createAnimal(Species.Snake).makeNoise());
    }
}

Output:
Neigh!
Cluck, cluck!
Hissss!

Thats a lot of code but the first 4 classes should be standard by now.  We have an interface called IAnimal forcing any classes that implement that interface to create their own implementation of the makeNoise() method.

The biggest addition to all of this (and the core of the factory method pattern) is the AnimalFactory class we created and only holds a single static method, createAnimal().  This method accepts a single parameter which is an enum that was also created called Species and holds the three types of animals that can be created.  Alternatively, if you were given access to the actual subtype of the object you can check that (however that is more specific to certain languages).  Using the type you don't have to make sure the enum is constantly updated.

makeNoise() simply contains a switch...case statement checking for the different possible inputs to this method and then returns a new instance of whichever animal is appropriate for that argument.  Note, typically you should throw some kind of error if the switch doesn't find a case that applies to that argument.  In this case we're just returning null which would blow up on us if we added something to the enum and didn't modify the method (see limitations of the pattern in the next section).

Finally we reach our common game class (RDRGame) with the standard Main() method.  Inside we simply invoke the createAnimal() method three times which returns us an IAnimal object.  Through the interface and (kind of) use of polymorphism we can invoke the makeNoise() method and voila, we have 3 distinct animals making noise.

Quick Note: Alternatively we could have just looped through the Species enum and passed the iterator variable as the argument.  Also, instead of an enum we could have used several other ways to define what we wanted like strings or even numbers (though not recommended).

Limitations

Thats it, the factory method pattern!  It's pretty obvious how this pattern can become extremely useful when you have a structure of differing object sub-types and need to be able to create one on the fly.  Plus, all the nasty code for checking what type you want to create is in one section and not littered throughout your project.

However, the factory method pattern suffers from immediate code rot as soon as a new parent type is added to the project.  At this point, if we wanted to add an IHuman interface we can't use this factory and need to write a whole new one (assuming IHuman isn't inheriting from IAnimal).

Conclusion

This pattern can be arguably considered less difficult to implement but more difficult to understand than the Singleton pattern we looked at before.  As with all design patterns, this one should only be used when needed; i.e. when we need to cleanly seperate out common subtypes of a given parent class.

Latest Jobs

Xbox Game Studios

Redmond, Washington
10.5.22
Technical Lighting Artist

Innogames

Hamburg, Germany
10.5.22
Game Designer - Elvenar

Six Foot

Houston, TX
10.3.22
Six Foot Director, Player Relations

Hometopia Inc.

Remote
10.7.22
Lead Engineer
More Jobs   

CONNECT WITH US

Explore the
Subscribe to
Follow us

Game Developer Job Board

Game Developer Newsletter

@gamedevdotcom

Explore the

Game Developer Job Board

Browse open positions across the game industry or recruit new talent for your studio

Browse
Subscribe to

Game Developer Newsletter

Get daily Game Developer top stories every morning straight into your inbox

Subscribe
Follow us

@gamedevdotcom

Follow us @gamedevdotcom to stay up-to-date with the latest news & insider information about events & more