Factory Design Pattern in C# – ScottLilly.com (2024)

Last updated on September 15, 2023

One of the practices I want to use in my Precise Programming is to instantiate all objects through factories.

This will add a little more complexity, because it is another class I’ll need to create. However, I believe the benefits it adds (through additional flexibility) will outweigh the cost of creating the new class.

If you prefer a video, you can watch this lesson here:

What is the factory pattern?

The factory design pattern is a different way to instantiate objects.

Instead of creating a new object by calling the class constructor, you call another function (the “factory”) that constructs the object.

Why would you use a factory to instantiate objects?

An object factory can help if you ever need to change the way you construct your objects.

You might need to do this if your objects use classes from another library. The other library may change its behavior, or requirements, when you upgrade to a newer version.

You may also want to do something new with the objects – log that they were created, use them in a queue, attach eventhandlers to them, etc.

With a factory, you might be able to make the change once (inside the factory method) instead of making it several places (every other place in your project that would have instantiated the object).

For these examples, we will create a Player object for a role-playing game.

Code sample (before, without a factory)

Player.cs

public class Player{ public int HitPoints { get; private set; } public int ExperiencePoints { get; private set; } public int Gold { get; private set; } public Player(int hitPoints, int experiencePoints, int gold) { HitPoints = hitPoints; ExperiencePoints = experiencePoints; Gold = gold; }}

With this technique, every place we want to create a new Player object, we would write code like this:

Player player = new Player(10, 0, 10);

Code sample (with factory inside the business object class)

One way to create a factory is to add a static method to the class we want to instantiate.

We can call this static method without an instance of the object. It will create a new instance of the Player class, and return it to the calling code.

We’ll also change the scope of the class constructor to “private”, so it can only be called by other methods in the Player class. Now, no other part of our program can call the constructor. They must use the factory method.

Player.cs

public class Player{ public int HitPoints { get; private set; } public int ExperiencePoints { get; private set; } public int Gold { get; private set; } private Player(int hitPoints, int experiencePoints, int gold) { HitPoints = hitPoints; ExperiencePoints = experiencePoints; Gold = gold; } public static Player CreateNewPlayer(int hitPoints, int experiencePoints, int gold) { return new Player(hitPoints, experiencePoints, gold); }}

Now, we create a Player object in the rest of our program by calling the factory method:

Player player = Player.CreateNewPlayer(10, 0, 10);

This is a factory method, but it doesn’t help us out very much. Not much has changed. We still call a method on the business object, and it returns a new Player object.

So, let’s see what happens with a more useful example – when you have a separate factory class, to create a player object from saved game data.

Code sample (with a separate factory class)

We need to change the scope of the Player class constructor to “internal”, from “private”, since we will call the constructor from a different class (our factory class) that is still in the same assembly/project. So now, it looks like this:

Player.cs

public class Player{ public int HitPoints { get; private set; } public int ExperiencePoints { get; private set; } public int Gold { get; private set; } internal Player(int hitPoints, int experiencePoints, int gold) { HitPoints = hitPoints; ExperiencePoints = experiencePoints; Gold = gold; }}

We’ll create a new class that will be a factory to (eventually) create Player objects from wherever we store the saved game data. For this first version, we won’t look for saved data.

PlayerFactory.cs

public static class PlayerFactory{ public static Player LoadPlayer() { return new Player(10, 0, 10); }}

Now, when we want to create a new Player object, our code would look like this:

Player player = PlayerFactory.LoadPlayer();

Next, we’ll expand the factory to load the player data from an XML file.

PlayerFactory.cs

public static class PlayerFactory{ public static Player LoadPlayer() { if(File.Exists("SavedGameData.xml")) { // For this demo, pretend we read these values from the XML file. int xmlHitPoints = 20; int xmlExperiencePoints = 123; int xmlGold = 56; return new Player(xmlHitPoints, xmlExperiencePoints, xmlGold); } else { return new Player(10, 0, 10); } }}

When we want to load a Player object, our calling code does not need to change. It still looks like this:

Player player = PlayerFactory.LoadPlayer();

If we decide to read saved game data from a SQL database, or from the Internet, or any other place, we only need to change the internals of the LoadPlayer method. The calling code always stays the same.

That’s where the factory method is very helpful. It allows us to make the change in one place, and not require that we make changes in several different places in our program.

Another way we can use an object factory

You can also use a factory method if you want to create objects that are different types – as long as they have the same base class, or implement the same interface.

In this situation, the return type of your factory method would be the base class, or the interface.

For example, let’s say we want to create monsters for our game. We have a base Monster class, with child classes of FlyingMonster, LandMonster, and SeaMonster.

Here are very simple versions of our monster classes:

Monster.cs

public class Monster{ public int HitPoints { get; set; }}

FlyingMonster.cs

public class FlyingMonster : Monster{ public int AirSpeed { get; set; }}

LandMonster.cs

public class LandMonster : Monster{ public int RunningSpeed { get; set; }}

SeaMonster.cs

public class SeaMonster : Monster{ public int SwimmingSpeed { get; set; }}

When we want a monster, let’s call our MonsterFactory, have it get a random number, and return a monster.

MonsterFactory.cs

public static class MonsterFactory{ public static Monster GetRandomMonster() { int randomNumber = 2; // Pretend we got a random number here. switch(randomNumber) { case 1: return new FlyingMonster(); case 2: return new LandMonster(); default: return new SeaMonster(); } }}

When we want a monster, we can call this code:

Monster monster = MonsterFactory.GetRandomMonster();

If we expand our game, to have more types of monsters, we only need to make the change in the GetRandomMonster() method – not the rest of our program.

Real-world example where the factory design pattern helped me

I once worked on a project that translated work requests between multiples programs. A work request would be submitted to our program, it would determine what format the request was in, where it needed to be sent, and what format was needed for the program it was being sent to.

Once the program knew the two formats, it would instantiate a translator object that knew how to do the conversion between those two formats.

When the conversion was done, the convertor objects should have released their memory. However, they had a bug, and held on to the memory they were using. After we did a few thousand conversions, our program would crash.

Fortunately, we were creating the convertor objects with a factory.

So, all I had to do was go into the factory class and change the code to re-use convertor objects, instead of constantly creating new ones. After that change, there would only ever be one of each type of convertor object – which didn’t take up much memory.

All my design pattern lessons

Source code for my design pattern lessons

I am a seasoned software engineer and design pattern enthusiast with extensive hands-on experience in the realm of Precise Programming. My expertise spans a wide range of software development practices, and I have a profound understanding of design patterns, their implementation, and their practical applications. Allow me to delve into the article and provide comprehensive insights into the concepts it covers.

1. Factory Pattern Overview: The article introduces the Factory Design Pattern as a method to instantiate objects differently than the conventional class constructor approach. Instead of directly calling the constructor, a separate function, referred to as the "factory," is employed to construct the object.

2. Motivation for Using a Factory: The article outlines scenarios where a factory pattern proves beneficial. Notably, it addresses cases where changes in object construction are necessary due to external factors, such as changes in external libraries or the need for additional functionalities like logging or event handling.

3. Code Samples Without a Factory: The initial code sample presents a Player class with a traditional constructor for creating instances. This method requires repetitive code each time a new Player object is instantiated.

4. Factory Inside the Business Object Class: The article demonstrates the integration of a factory method within the Player class, rendering the constructor private and providing a static factory method to instantiate Player objects. This approach consolidates object creation logic within the class.

5. Factory in a Separate Class: To enhance flexibility, the article introduces a separate factory class, PlayerFactory. The Player class constructor is adjusted to "internal" scope, and the PlayerFactory class is responsible for creating Player objects based on saved game data.

6. Handling Different Data Sources: The article expands on the factory pattern's versatility by illustrating how the PlayerFactory class can evolve to load player data from various sources, such as an XML file. This showcases the pattern's ability to adapt to changing requirements without altering external code.

7. Creating Objects of Different Types: The article extends the application of the factory pattern to handle the creation of objects of different types sharing a common base class or interface. The MonsterFactory example demonstrates how diverse monsters (FlyingMonster, LandMonster, SeaMonster) can be instantiated through a single factory method.

8. Real-World Example: A real-world example is presented where the factory pattern proved instrumental in addressing a memory management issue in a project involving translation of work requests between multiple programs. The use of a factory facilitated a swift and centralized fix to the problem.

In conclusion, the factory design pattern, as illustrated in the article, provides a powerful tool for enhancing flexibility, adaptability, and maintainability in software development, making it a valuable addition to the toolkit of any programmer engaged in Precise Programming.

Factory Design Pattern in C# – ScottLilly.com (2024)
Top Articles
Latest Posts
Article information

Author: Ray Christiansen

Last Updated:

Views: 6323

Rating: 4.9 / 5 (69 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Ray Christiansen

Birthday: 1998-05-04

Address: Apt. 814 34339 Sauer Islands, Hirtheville, GA 02446-8771

Phone: +337636892828

Job: Lead Hospitality Designer

Hobby: Urban exploration, Tai chi, Lockpicking, Fashion, Gunsmithing, Pottery, Geocaching

Introduction: My name is Ray Christiansen, I am a fair, good, cute, gentle, vast, glamorous, excited person who loves writing and wants to share my knowledge and understanding with you.