Patterns 101 - Factory Pattern

Note: This is part of an ongoing series introducing patterns at the Tampa C# Meetup.

Purpose

The factory pattern, formally called the** Abstract Factory Pattern**, abstracts the creation of a concrete class.factory

Basics

Using this pattern requires 4 things.

  1. A base class or interface that the created concrete classes derive from
  2. An abstract class or interface base with a method that has a return type signature from #1
  3. One or more concrete classes derived from the type in #1
  4. A number of concrete creation classes derived from the type in #2 with an implementation to the creation method returning a concrete class

Derivatives

It is possible to implement this pattern with using the creation class, and instead using a method, or in .NET a delegate. This is sometimes referred to as the Factory Method Pattern.

Abstract Factory Implementation

Since I am very tired of the animals or cars class hierarchies, I chose televisions for my hierarchy.

Base Class for Concrete Types

{% gist dbuksbaum/d59d0726000f623c0114 Television.cs %}

Interface for the Creation Type

{% gist dbuksbaum/d59d0726000f623c0114 ITelevisionCreator.cs %}

Concrete Types

{% gist dbuksbaum/d59d0726000f623c0114 LCD.cs %}

Concrete Creator Classes

{% gist dbuksbaum/d59d0726000f623c0114 CreatorLEDTelevision.cs %}

Test Case

I have created a simple method that will take the interface to the creation class, creates the type, and calls a few methods.

private static void TestTelevision(ITelevisionCreator tvCreator)
{
  var tv = tvCreator.CreateTelevision();
  tv.TurnOn();
  tv.SetChannel(100);
  tv.TurnOff();
}

And here is how I call the test method for each factory.

Console.WriteLine("Using Abstact Factory");
TestTelevision(new CreatorLCDTelevision());
TestTelevision(new CreatorLEDTelevision());
TestTelevision(new CreatorPlasmaTelevision());

Factory Method Implementation

Since I seem to run into the factory method model more often, I wanted to show the implementation as it compares to the Abstract Factory Pattern. The key change is that we require a creation method instead of a creation class.

Test Case with Delegates

Console.WriteLine("Using Delegate Creator");
TestTelevision(new CreatorLCDTelevision().CreateTelevision);
TestTelevision(new CreatorLEDTelevision().CreateTelevision);
TestTelevision(new CreatorPlasmaTelevision().CreateTelevision);    

As you can see, I am still using the concrete creation classes, but now passing in the creation method as a delegate.

Here is the code for the test case.

private static void TestTelevision(Func<Television> tvCreator)
{
  var tv = tvCreator();
  tv.TurnOn();
  tv.SetChannel(100);
  tv.TurnOff();
}

As you notice, there are only two changes.

  • Change 1 – The signature for the method entry changes from taking the interface to taking a delegate that returns the Television base class (line 1)
  • Change 2 – The actual creation call is now just a delegate method call instead of instance method call (line 2)

While this is not a significant change in the amount of code or function, it increases the flexibility. Let me show you some of that flexibility.

Console.WriteLine("Using Lambda Creator");
TestTelevision(() => new LCD());
TestTelevision(() => new LED());
TestTelevision(() => new Plasma());

Conclusion

In the final test case of the **Factory Method Pattern **version, the creation classes have been completely replaced by lambda delegates. This eliminates a few types, specifically 4 in this case. Where this becomes very useful, is now it is possible to store those delegates in a collection, perhaps a Dictionary, and select it based on some input criteria, such as a type id. This creates a basic jump table from a type to a method to create that type. This is the basic functionality needed for an Inversion of Control container.

As I mentioned earlier on, this pattern is used heavily in many frameworks. One example is in Caliburn.Micro. Here is a the ElementConvention.cs source:

The ElementConvention class provides two factories, GetBindableProperty and CreateTrigger. It uses a C# field to replace these factories with user defined model using simple assignment, and the remainder of the Caliburn.Micro framework will go to this class use those factories.

The reason I consider this more flexible than the Abstract Factory Pattern, is that I do not need to create a creation base class, or any of the concrete creation classes. It is replaced by the Func generic delegate, and a delegate implementation based on a lambda or a instance method or a static class method.

As a reminder, these Patterns 101 posts are just meant to be quick example of commonly used patterns as implemented in C#. Please feel free to suggest patterns of interest of you, or even use cases you would like to see. Of course, you can just drop into the Tampa C# Meetup as I present these posts for our Patterns 101 segment.

Related

comments powered by Disqus