Factory Method Design Pattern

patzistar

Patrick Schadler

Posted on January 30, 2020

Factory Method Design Pattern

This post was originally published here.

Factory Method Design Pattern

In today's episode of Software Design Patterns you will learn everything about the Factory Method Design Pattern. The Factory Method is a creational pattern. That means that the pattern has something to do with object creation. There are different types of design patterns. The other types are structural and behavioral. Those types will have a dedicated blog post in the future. For reference - the last article covered the Singleton Design Pattern - which is also a creational pattern. All the examples, source code and unit tests are in this GitHub repository.

GitHub logo DonkeyKongJr / FactoryMethodPattern

This Repository hosts how a Factory Method Design Pattern could be used.

FactoryMethodPattern

Codacy Badge CircleCI

This Repository hosts how a Factory Method Design Pattern could be used.

You find an up-to-date description in the related blog post here. (Yet to come)

For any changes or updates please file a Pull Request.




What’s the purpose of the Factory Method Design Pattern?

The Factory Method is a very common pattern, but strongly misused. I have seen many examples where methods were named factory, but did something completely different. The quote below - taken from the Gang of Four - is very precise about the Factory Method. The Factory Method Design Pattern defines an interface for creating an object, but let sub classes decide which class to instantiate. Factory Method lets a class defer instantiating to sub classes. [1]

Don't fall into the trap and use it for everything. If you are not sure about when to use, you probably don't need it anyway.

How does the Factory Method looks like?

In the picture below you find the Unified Modeling Language (UML) diagram. Factory As mentioned at the beginning you find all the code examples in a working project on GitHub.

public interface ICar
{
    string GetName();
    void Accelerate();
    void Break();
}
Enter fullscreen mode Exit fullscreen mode
public class ElectricCar : ICar
{
    public int Speed { get; private set; }

    public string GetName()
    {
        return "Electric";
    }

    public void Accelerate()
    {
        Speed = Speed + 2;
    }

    public void Break()
    {
        if (Speed > 0)
        {
            Speed--;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
public class PetrolCar : ICar
{
    public int Speed { get; private set; }

    public string GetName()
    {
        return "Petrol";
    }

    public void Accelerate()
    {
        Speed++;
    }

    public void Break()
    {
        if (Speed > 0)
        {
            Speed--;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example we have an interface ICar.cs, which provides basic car operations like accelerate and break. In addition to that we have an GetName() method, were the concrete implementation should return the actual name of the car.

public class CarFactory
{
    public ICar CreateCar(string type)
    {
        if (string.Equals(type, "Petrol", StringComparison.OrdinalIgnoreCase))
        {
            return new PetrolCar();
        }

        if (string.Equals(type, "Electric", StringComparison.OrdinalIgnoreCase))
        {
            return new ElectricCar();
        }

        throw new NotSupportedException($Car Type '{type}' is not supported);
    }
}
Enter fullscreen mode Exit fullscreen mode

Our Factory, called CarFactory.cs, is responsible for creating instances of concrete cars. We provide a dedicated CreateCar(string type) method, where the desired type can be passed as an argument. The method maps the type to a concrete implementation. This can be done via multiple if clauses or a switch statement. Anyway, if there is no matching type we throw an NotSupportedException to make it clear that the factory does not support the desired type. To see the proper use of the CarFactory look into the test project.

public class CarFactoryTest
{
    [Theory]
    [InlineData("Electric")]
    [InlineData("electric")]
    [InlineData("eLeCtriC")]
    public void ShouldCreateElectricCarInstance(string type)
    {
        var carFactory = new CarFactory();
        var car = carFactory.CreateCar(type);

        car.Should().BeOfType<ElectricCar>();
        car.GetName().Should().Be("Electric");
    }

    [Theory]
    [InlineData("Petrol")]
    [InlineData("petrol")]
    [InlineData("pEtRoL")]
    public void ShouldCreatePetrolCarInstance(string type)
    {
        var carFactory = new CarFactory();
        var car = carFactory.CreateCar(type);

        car.Should().BeOfType<PetrolCar>();
        car.GetName().Should().Be("Petrol");
    }

    [Theory]
    [InlineData("hans")]
    [InlineData("car")]
    [InlineData("electricpetrol")]
    public void ShouldThrowNotSupportedExceptionWhenTypeIsInvalid(string type)
    {
        var carFactory = new CarFactory();
        Action getCar = () => carFactory.CreateCar(type);

        getCar.Should().ThrowExactly<NotSupportedException>();
    }
}
Enter fullscreen mode Exit fullscreen mode

If you have any questions or comments feel free to leave them below. That’s it. Happy coding as always.

References[1] -Design patterns, software engineering, object-oriented programming

💖 💪 🙅 🚩
patzistar
Patrick Schadler

Posted on January 30, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Builder Design Pattern
softwaredesignpattern Builder Design Pattern

February 27, 2020

Factory Method Design Pattern
softwaredesignpattern Factory Method Design Pattern

January 30, 2020

Singleton Design Pattern in c#
softwaredesignpattern Singleton Design Pattern in c#

January 20, 2020