Factory Method Pattern in C#

Factory Method Pattern in C#

Originally posted here

The Factory Method is a creational design pattern that allows the abstraction of object creation. It defines a method for creating an instance based on a superclass but allows subclasses to alter the type of objects that they create.

You can find the example code of this post, on GitHub.

Conceptualizing the Problem

Imagine that we are working for a logistics company that hired us to create a logistics management application. The company is small and has some trucks to handle transportation. Thus our application can only transport goods via truck, and the bulk of our code lives inside the Truck class.

Thanks to our application the company gains traction and growing exponentially. Eventually, the company buys a cargo ship and now wants us to incorporate sea logistics into the app.

That's great news, but how about the code? Currently, most of the code is coupled to the Truck class. Adding a Ship class into the application would require architectural-level changes to the entire codebase. Moreover, if later we need to add another type of transportation to the application, we will probably need to make all of these changes again.

As a result, we will end up with a nasty codebase, riddled with conditionals that alter the application's behaviour depending on the transportation mode.

The Factory Method pattern suggests that we should replace direct object construction calls (using the `new` operator) with calls to a factory method. Objects returned by a factory method are often referred to as products.

Initially, this change does not make any sense: we just moved the constructor call from one part of the code to another. However, now we can override the factory method in a subclass and change the products being created by the method.

There's a limitation though: subclasses may be able to return different types of products, but these products must have a common base class or interface. 

Back to our logistics application, both Truck and Ship classes must implement a common interface, for example, ITransport, which declares a method called Deliver. The classes can implement the interface differently: the Truck class is concerned with cargo delivery by land, while the Ship class is concerned with cargo delivery by sea.

The client using the factory method does not see a difference between the actual products returned by each subclass. The client treats all the products as abstract ITransport objects. The client also knows that all ITransport objects must implement some Deliver method, but how each of them implements it doesn't matter.

Structuring the Factory Method Pattern

In its base implementation, the Factory Method pattern has four participants:

No alt text provided for this image

  • Product: The Product declares an interface, which is common to all objects that can be produced by the creator and its subclasses.
  • Concrete Products: Concrete Products are different implementations of the product interface.
  • Creator: The Creator class declares the factory method that returns new product objects. The return type of this method must match the product interface. We can declare the factory method abstract to force all subclasses to implement their versions of the method. As an alternative, the base factory method can return some default product types. Note, that despite its name, product creation is not the primary responsibility of the creator. Usually, the creator class already has some core business logic related to products. The factory method helps to decouple this logic from the concrete product classes. Here is an analogy: a large software development company can have a training department for developers. However, the primary function of the company as a whole is still writing code, not producing developers.
  • Concrete Creators: The Content Creators override the base factory method so it returns a different type of product.

To demonstrate how the Factory Method pattern works, we are going to create...a sandwich. According to Wikipedia:

A sandwich is a food typically consisting of vegetables, sliced cheese or meat, placed on or between slices of bread, or more generally any dish wherein bread serves as a container or wrapper for another food type.

To start, we will implement some Product participants, which will be the ingredients that comprise the sandwiches. We'll create an abstract Ingredient class to represent them:

No alt text provided for this image

Now let's instantiate a few classes to represent ingredients in sandwiches (our CocreteProduct participants):

No alt text provided for this image
No alt text provided for this image
No alt text provided for this image
No alt text provided for this image
No alt text provided for this image

What we want to do now is to create a factory that will allow us to build different kinds of sandwiches using the same set of ingredients. What will differ between the kinds of sandwiches will be the amount and order of said ingredients.

First, let's build an abstract class Sandwich that represents all possible kinds of sandwiches. This is the Creator participant:

No alt text provided for this image

Note the CreateIngredients() method. This method is the Factory Method which gives the pattern its name. It's not implemented here because that implementation is left to the ConcreteCreator classes that we now need to define. Let's start with a Reuben sandwich:

No alt text provided for this image

Whenever we create an object of class ReubenSandwich, we can call CreateIngredients()` to create the correct amount and order of ingredients for this sandwich.

Let's create a GrilledCheeseSandwich now:

No alt text provided for this image

Now we can create the sandwich in our Main method:

No alt text provided for this image

And as always, the output of this method will be the following:

No alt text provided for this image

Comparison of Different Factories

There are different references to the term Factory around the web. Though they might look as all referring to the same thing, they all have different meanings.

Let's try to figure out their differences.

Factory

The Factory is an ambiguous term that causes the most confusion. This term stands for a function method or class that is supposed to be producing something. Most commonly, factories produce objects. But they can also produce files, records to a database, logs, etc.

Any of the following can be referred to as a factory:

  • A function or method that generates an application's GUI
  • A class that creates users
  • A static method that calls a class constructor in a certain way
  • One of the creational design patterns

When someone uses the factory, the meaning of it is supposed to be clear from the context, but still causes headaches and confusion, especially in legacy codebases.

Creation Method

Joshua Kerievsky defines a Creation Method as a method that creates objects. This means that every result of a factory method pattern is a creation method but not necessarily the reverse. It also means that we can substitute the term creation method wherever Martin Fowler uses the term factory method in Refactoring.

In reality, the creation method is just a wrapper around a constructor call. It may just have a name that better expresses our intentions. On the other hand, it may help to isolate the code from changes to the constructor. It could even contain some particular business logic that would return existing objects instead of creating new ones.

A lot of people call this method a factory method just because it creates new objects. The logic is straightforward. The method creates objects and since all factories create objects, this method is a factory method. As a consequence, there's a lot of confusion between creation methods and factory methods.

The following Next method is a creation method:

No alt text provided for this image

Static Creation Method

A Static Creation Method is a creation method declared as static.

While many people call these static creation methods. That is wrong. The Factory Method is a design pattern based on inheritance. If you make it static, you can no longer extend it via subclassing, which defeats the purpose of the pattern.

When a static creation method returns a new object, it becomes an alternative constructor.

This might be helpful when:

  • We need several different constructors that have different purposes but their signatures match. For instance, having both Random(int max) and Random(int min) is impossible in Java, C++, C#, and many other languages. The most common workaround is to create several static methods that call the default constructor and set appropriate values afterwards.
  • We want to reuse existing objects, instead of instancing new ones (see also, the Singleton pattern). Constructors, in most programming languages, have to return new class instances. The static creation method is a workaround to this limitation. A static method can decide whether to create a fresh instance by calling the constructor or returning an existing object from some cache.

In the following example, the Load method is a static creation method. It provides a convenient way to retrieve users from a database.

No alt text provided for this image

Simple Factory Method

The Simple Factory describes a class that has a single creation method with a large conditional, that decides the product class based on the method parameters.

Simple factories are usually confused with general factories or with one of the creational design patterns. In most cases, a simple factory is an intermediate step in introducing the Factory Method or Abstract Factory patterns.

A simple factory is usually represented by a single method in a single class. Over time, this method might become too big, so we might decide to extract parts of the method into subclasses. Once we do it several times, the whole thing will turn into the classic factory method pattern.

Here's an example of a simple factory:

No alt text provided for this image

Factory Method Pattern

The Factory Method is a creational design pattern that provides an interface for creating objects but allows subclasses to alter the type of object that will be created.

If you have a creation method in the superclass and several subclasses that extend it, you probably have a factory method in your hands.

No alt text provided for this image

Abstract Factory Pattern

The Abstract Factory is a creational design pattern that allows producing families of related or dependent objects without specifying their concrete classes.

For instance the classes Transport, Engine and Controls. There are might be several variants like Car, CombustionEngine and SteeringWheel or Ship, Waterjet Engine and Helm.

If you don't operate with product families, then you don't need an abstract factory.

A lot of people mix up the abstract factory pattern with a simple factory class declared as abstract. Don't do that.

Pros and Cons of Factory Method Pattern

No alt text provided for this image

Relations with Other Patterns

  • Many designs start by using the Factory Method and evolve toward Abstract Factory, Prototype or Builder.
  • Abstract Factory classes are often based on a set of Factory Methods.
  • The Factory Method is a specialization of the Template Method. At the same time, a Factory Method may serve as a step in a large Template Method.

Final Thoughts

In this article, we have discussed what is the Factory Method pattern, when to use it and what are the pros and cons of using this design pattern. We also examined different types of factories and how the Factory Method pattern relates to other classic design patterns.

The Factory Method design pattern lets us leave the type of created object on the subclasses.

It enables us to define an interface through which the client will create the object. Its main purpose is to hide the object creation logic from the client. It is also known as a virtual constructor.

It's worth noting that the Factory Method pattern, along with the rest of the design patterns presented by the Gang of Four, is not a panacea or a be-all-end-all solution when designing an application. Once again it's up to the engineers to consider when to use a specific pattern. After all these patterns are useful when used as a precision tool, not a sledgehammer.

To view or add a comment, sign in

More articles by Konstantinos Kalafatis

  • Premises of Software Architecture

    This post is the first of a series of posts around Software Architecture. In this series we are going to discuss what…

  • Adapter Pattern in C#

    Originally posted here The Adapter is a structural design pattern that allows objects with incompatible interfaces to…

  • Visitor Pattern in C#

    The Visitor is a behavioural design pattern that lets us separate algorithms from the entities on which they operate…

  • Observer Pattern in C#

    Originally posted here The Observer is a behavioural design pattern that lets us define a subscription mechanism to…

  • Mediator Pattern in C#

    Originally posted here The Mediator is a behavioural design pattern that lets us reduce chaotic dependencies between…

  • Singleton Pattern in C#

    Originally posted here The Singleton is a creational design pattern that lets us ensure that a class has only one…

  • Composite Pattern in C#

    Originally posted here The Composite is a structural design pattern that allows us to compose objects into tree…

  • Decorator Pattern in C#

    Originally posted here The Decorator is a structural design pattern that lets us attach new behaviours to objects by…

  • Builder Pattern In C#

    Originally posted here The Builder is a creational design pattern that allows us to construct complex objects step by…

    1 Comment
  • Application Caching Strategies

    Originally posted here Most, if not all, developers are at least somewhat familiar with the concept of caching. After…

Insights from the community

Others also viewed

Explore topics