Code Review Videos > Design Patterns > Factory Pattern Example in C#

Factory Pattern Example in C#

The following code and tests work towards the same outcome as achieved in the TypeScript implementation of the Simple Factory pattern.

The aim here is to compare and contrast against the TypeScript code whilst learning C#.

namespace DesignPatterns.Creational;

public enum VehicleType
{
    Car,
    Bike,
}

public interface IVehicle
{
    public string Move();
}

internal class Car : IVehicle
{
    public string Move()
    {
        return "Driving a car...";
    }
}

internal class Bike : IVehicle
{
    public string Move()
    {
        return "Riding a bike...";
    }
}

public static class SimpleFactory
{
    public static IVehicle CreateVehicle(VehicleType vehicleType)
    {
        return vehicleType switch
        {
            VehicleType.Car => new Car(),
            VehicleType.Bike => new Bike(),
            _ => throw new ArgumentException("Invalid vehicle type.")
        };
    }
}Code language: C# (cs)

And the associated NUnit tests:

using System;
using DesignPatterns.Creational;
using NUnit.Framework;

namespace DesignPatternsUnitTests.Creational;

public class Tests
{
    [Test]
    public void ShouldCreateACar()
    {
        var vehicle = SimpleFactory.CreateVehicle(VehicleType.Car);

        Assert.AreEqual(vehicle.Move(), "Driving a car...");
    }

    [Test]
    public void ShouldCreateABike()
    {
        var vehicle = SimpleFactory.CreateVehicle(VehicleType.Bike);

        Assert.AreEqual(vehicle.Move(), "Riding a bike...");
    }

    [Test]
    public void ShouldThrowForAnInvalidVehicleType()
    {
        Assert.Throws<ArgumentException>(() =>
            SimpleFactory.CreateVehicle((VehicleType)999), "Invalid vehicle type");
    }
}
Code language: C# (cs)

Mostly this code is very similar to the TypeScript approach.

However, there are a few interesting differences to cover.

public enum VehicleType

Both C# and TypeScript support defining enums using the enum keyword.

During this process I learned that in C# you can define the underlying type of an enum, for example setting the type to byte, or short, or int.

By default, int is used.

In TypeScript, there is only number.

Taking the enum from the code above, I could specify the underlying type to be short as follows:

public enum VehicleType : short
{
    Car,
    Bike,
}Code language: C# (cs)

I’m not really sure why I might want or need to do this, but it’s interesting to know all the same.

I do know a short goes from -32,768 to 32,767… so it seems unlikely I’d ever actually need the full range of values that an int provides. But hey, who am I to make wild claims like that at this stage?

What I do know is that I cannot use string values as the underlying type, like I can in TypeScript:

Keeping Implementations internal

Rather than spilling out the guts / internals of my Car and Bike classes, I made use of the internal keyword when defining my classes:

internal class Car : IVehicle
{
    public string Move()
    {
        return "Driving a car...";
    }
}
Code language: C# (cs)

My theory here is that if I am masking away the object creation behind the SimpleFactory, I might not want to expose the classes directly.

As best I understand it,internal will mean only code within my current Project would be able to directly instantiate new instances of those classes.

However I did have to make the IVehicle and VehicleType both public. Otherwise, how would outside callers be able to work with the code?

Pattern Matching Using switch

Hands down my favourite part of this code is the switch expression.

There’s two reasons I love this:

  1. Being able to directly return the switch outcome, and;
  2. Pattern matching on the VehicleType value

Pattern matching itself is a really nice feature I first learned about in Elixir. That is one thing I really, really hope comes to TypeScript / JavaScript some time soon.

Direct returns from a switch expression are just lovely.

Unlike the exhaustive switch approach from TypeScript, we have the two matches and then the default case (_ => …) which acts as our catch all.

The one downside here is that adding in a new value to the enum does not blow everything up:

Talk about subtle. A tiny green (my eyes!) line under the “s”. Not hard to miss at all.

There is perhaps a better way here, so if you know it, please shout up in the comments.

Requiring Assert.Throws

As a result of not being able to implement an exhaustive switch, I have had to re-introduce a unit test I was able to eliminate in the TypeScript code:

[Test]
public void ShouldThrowForAnInvalidVehicleType()
{
    Assert.Throws<ArgumentException>(() =>
        SimpleFactory.CreateVehicle((VehicleType)999), "Invalid vehicle type");
}Code language: C# (cs)

In many ways this is like the Jest test code that works with exceptions.

The code that is expected to fail is wrapped in a lambda. The outcome of that lambda is then, somehow, used by NUnit to determine that things went wrong as expected.

The second optional argument is the error message I expect.

But the trickiest part of this code was in figuring out how to provide a bad value to the CreateVehicle method.

Given that I had defined that CreateVehicle accepts the VehicleType enum, and I only have two allowable values in there, I had to figure out how to trick the code into running, in order to get the fail I desired.

What I’m doing here is casting any random value – 999 in this case – to be a VehicleType. That was sheer luck really. I figured hey, I just learned an enum is int underneath, can I trick it somehow by pretending any int is a valid value in that enum. And it worked.

Sometimes I get lucky.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.