DaedTech

Stories about Software

By

Factory Method

Quick Information/Overview

Pattern Type Creational
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Moderate — slightly easier than Abstract Factory

Image courtesy of dofactory

Up Front Definitions

  1. Creator: This is the basic, abstract factory interface.
  2. Concrete Creator: Inheritor factory classes that implement some actual object creation scheme.
  3. Product: This is the base/abstract polymorphic object that gets created by the factories.

The Problem

Let’s say that you’re coding up some kind of game and in this game a character navigates a world and encounters various entities with which to interact, including enemies. You’re starting out with a very bare bones proof of concept, and here is your sketch of some enemies:

public abstract class Enemy
{
public abstract string Attack();
}

public class Dragon : Enemy
{
public override string Attack()
{
return "You've been torched with fire breath!";
}
}

public class Gator : Enemy
{
public override string Attack()
{
return "You've been chomped!";
}
}

public class HouseFly : Enemy
{
public override string Attack()
{
return "You've been annoyed!";
}
}

public class MotherInLaw : Enemy
{
public override string Attack()
{
return "You've been guilt-tripped!";
}
}

public class ChuckNorris : Enemy
{
public override string Attack()
{
return "Your entire existence has been erased from space-time in one devastating but magnificent master-stroke!";
}
}

The concrete enemies return a string representation of their attack, which you will, no-doubt, later transform into some kind of first class attack object or even graphic as the game moves along, but for now, you just want to get the concept right. To get things going, you create the following class:

public class GameNarrative
{
public void MoveMainCharacterTo(string placeName)
{
if (placeName == "swamp")
InteractWithEnemy(new Gator());
}

private void InteractWithEnemy(Enemy enemy)
{
Console.Write(enemy.Attack());
}
}

You want to keep things clean, so you abstract an interaction method, knowing that at some point this will probably mean something different than dumping to Console. From there, you’re now left to figure out the enemy situation based on where the character goes and you’re off to a good start since gators tend to hang out in swamps. Let’s add in a few more scenarios:

public void MoveMainCharacterTo(string placeName)
{
if (placeName == "swamp")
InteractWithEnemy(new Gator());
else if (placeName == "starbucks" || placeName == "family reunion")
InteractWithEnemy(new MotherInLaw());
else if (placeName == "middleEarth")
InteractWithEnemy(new Dragon());
else if (placeName == "texas truck stop")
InteractWithEnemy(new ChuckNorris());
else
InteractWithEnemy(new HouseFly());
}

Now you’re off and running. You decide that HouseFly is a good enemy to use in this case, since it seems like a good stock enemy ala the “Goombas” in Super Mario Brothers or Foot Soldiers in the Teenage Mutant Ninja Turtles (I’m probably dating myself a bit here). But wait a minute — house flies could happen anywhere. Let’s say that they’re the else condition, but they also have a 50/50 chance of appearing in the other places. Hmmm… let’s introduce an abstraction to hide the ugly and annoying details of randomization and do this:

public void MoveMainCharacterTo(string placeName)
{
if (placeName == "swamp")
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new Gator());
else
InteractWithEnemy(new HouseFly());
}
else if (placeName == "starbucks" || placeName == "family reunion")
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new MotherInLaw());
else
InteractWithEnemy(new HouseFly());
}
else if (placeName == "middleEarth")
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new Dragon());
else
InteractWithEnemy(new HouseFly());
}
else if (placeName == "texas truck stop")
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new ChuckNorris());
else
InteractWithEnemy(new HouseFly());
}
else
InteractWithEnemy(new HouseFly());
}

Ew, that’s starting to smell a bit, but no time to worry about that now. Your efforts here have led to some angel investment capital and now the pressure is on. You use that money to hire a UX/gameplay expert so that he can worry about the gaming decisions while you focus on architecture. He tells you that you need to introduce the concept of difficulty and that Chuck Norris can be anywhere except Middle Earth but only if the difficulty level is set to 5 or more. But Chuck Norris is a family man himself, so he’ll only attack you at a family reunion on a really high difficulty level like 10. Otherwise, he’ll wait until you leave. Hmmm….

public void MoveMainCharacterTo(string placeName)
{
if (placeName == "swamp")
{
if (_difficultyLevel > 5)
{
switch (_randomizer.PickANumberOneThrough(3))
{
case 1: InteractWithEnemy(new Gator()); break;
case 2: InteractWithEnemy(new HouseFly()); break;
case 3: InteractWithEnemy(new ChuckNorris()); break;
}
}
else
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new Gator());
else
InteractWithEnemy(new HouseFly());
}
}
else if (placeName == "starbucks")
{
if (_difficultyLevel > 5)
{
switch (_randomizer.PickANumberOneThrough(3))
{
case 1: InteractWithEnemy(new MotherInLaw()); break;
case 2: InteractWithEnemy(new HouseFly()); break;
case 3: InteractWithEnemy(new ChuckNorris()); break;
}
}
else
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new MotherInLaw());
else
InteractWithEnemy(new HouseFly());
}
}
else if (placeName == "family reunion")
{
if (_difficultyLevel > 10)
{
switch (_randomizer.PickANumberOneThrough(3))
{
case 1: InteractWithEnemy(new Gator()); break;
case 2: InteractWithEnemy(new HouseFly()); break;
case 3: InteractWithEnemy(new ChuckNorris()); break;
}
}
else
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new Gator());
else
InteractWithEnemy(new HouseFly());
}
}
else if (placeName == "middleEarth")
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new Dragon());
else
InteractWithEnemy(new HouseFly());
}
else if (placeName == "texas truck stop")
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new ChuckNorris());
else
InteractWithEnemy(new HouseFly());
}
else
{
if (_difficultyLevel > 5)
{
if (_randomizer.IsRandomCoinFlipHeads())
InteractWithEnemy(new ChuckNorris());
else
InteractWithEnemy(new HouseFly());
}
else
InteractWithEnemy(new HouseFly());
}
}

You look at this and realize that you’re definitely whipping up some spaghetti code here, but no time for that now. Your game designer tells you that you need a new mode of the game where instead of interacting with the enemies you talk with them first. The logic for encountering the enemies is exactly the same and you still need your old code, but you need it in a new module. Oh, and you should probably add a few new enemies that you find in a few new places. And house flies should probably stop appearing after difficulty level 7. Oh, and dragons can appear in Starbucks sometimes after a successful battle with MotherInLaw. Oh, and gators can appear at your family reunion if you have it in Florida.

Here’s the code for that… just kidding. You’re probably not going to read subsequent posts if I destroy your eyesight with the code I’m describing.

So, What to Do?

As has become customary in this section, let’s examine what went wrong. Most of the time it’s the point at which copying and pasting start, but not in this case. Another good tell in this series of posts where things go off the rail is when I start trotting out excuses for what ‘you’ are doing in the second person narrative. As soon as things are a little ugly because ‘you’ have a deadline or ‘your’ project manager is riding you, that’s usually when things went wrong. Here is no exception. Let’s rewind to the second code snippet, representative of a simpler time:

public void MoveMainCharacterTo(string placeName)
{
if (placeName == "swamp")
InteractWithEnemy(new Gator());
else if (placeName == "starbucks" || placeName == "family reunion")
InteractWithEnemy(new MotherInLaw());
else if (placeName == "middleEarth")
InteractWithEnemy(new Dragon());
else if (placeName == "texas truck stop")
InteractWithEnemy(new ChuckNorris());
else
InteractWithEnemy(new HouseFly());
}

This is alright, though I would argue that we can make a nice improvement here. Notice that we’re following a pretty consistent pattern here: we check place name and then we invoke the same method on a polymorphic object that varies with place name. It might seem like a trivial bit of redundancy, but these add up as you leave them in and, I would argue, poison the well when it comes to future design decisions. Broken Window Theory and all that. So let’s change the code to this:

public void MoveMainCharacterTo(string placeName)
{
var enemy = GenerateLocalEnemyFor(placeName);
InteractWithEnemy(enemy);
}

private static Enemy GenerateLocalEnemyFor(string placeName)
{
switch (placeName)
{
case "swamp": return new Gator();
case "starbucks":
case "family reunion": return new MotherInLaw();
case "middleEarth": return new Dragon();
case "texas truck stop": return new ChuckNorris();
default: return new HouseFly();
}
}

Notice that there’s now only one call to “InteractWithEnemy” and we’ve split the functionality of mapping place name to en enemy instance from the functionality of interacting with the enemy in a nod to the SRP. You also might notice that we have implemented what has come to be a common variant of the original Factory Method pattern, which is the static factory method. A static factory method is a stateless method that takes in some criteria and spits back a matching polymorphic instance of the common base return type. For instance, this method says “if the place is middle earth, we need a dragon enemy.”

With this refactoring accomplished, let’s take on the next requirement, which is that house flies can occur anywhere with a 50% probability. Before our heads start rushing with design patterns and complex implementations, let’s consider what might be the easiest way to get this working. Didja think of this:

public void MoveMainCharacterTo(string placeName)
{
var enemy = GenerateLocalEnemyFor(placeName, _randomizer);
InteractWithEnemy(enemy);
}

private static Enemy GenerateLocalEnemyFor(string placeName, IRandomizeThings randomizer)
{
if (randomizer.IsRandomCoinFlipHeads())
return new HouseFly();

switch (placeName)
{
case "swamp": return new Gator();
case "starbucks":
case "family reunion": return new MotherInLaw();
case "middleEarth": return new Dragon();
case "texas truck stop": return new ChuckNorris();
default: return new HouseFly();
}
}

Notice how easy that is with a little bit of logic separation. But, if that implementation strategy were going to hold up, there’d be no meat to this post, so let’s press on. Chuck Norris can be anywhere except for Middle Earth and a family reunion if the difficulty level is at least 5 and anywhere except Middle Earth if the difficulty level is at least 10. At this point it’s important to recognize what’s happening here and it’s easier to do so now with this factored road down which we’ve started. What’s happening is that what was originally a simple mapping from place name to enemy inheritor is becoming muddied by a growing number of additional factors. And what’s a good way to handle additional complexity in an object oriented programming language? Well, encapsulate it in an object.

The idea of centering the enemy generation around places is appealing since that’s how we originally conceived of it, so let’s stick with that. The family reunion one seems to be the most complicated, so let’s take a look at that:

public class FamilyReunionFactory
{
private readonly IRandomizeThings _randomizer;

public FamilyReunionFactory(IRandomizeThings randomizer)
{
_randomizer = randomizer;
}

public Enemy GetEnemy(int difficultyLevel)
{
if (difficultyLevel < 10)
return _randomizer.ChooseAtRandom(new HouseFly(), new MotherInLaw());
else
return _randomizer.ChooseAtRandom(new HouseFly(), new MotherInLaw(), new ChuckNorris());
}
}

(I added a “choose at random” method to the interface of signature T ChooseAtRandom<T>(params T[] thingsToChoose) to keep the emphasis on the factory class as much as possible rather than distracting with worries about random implementation. I acknowledge that this would have made the problem code a little less noisy, but it still would have been headed down a bad street with creeping complexity)

Cool! Now the GameNarrative class doesn’t need to worry about the creeping complexity around what goes into the decision of which enemy to generate beside the place name. We have a class with the single responsibility of figuring out how enemies get generated for the family reunion location. But how does this fit with the original class? Well, let’s take a look at an interim solution. Here is an updated, no-longer-static factory method:

private Enemy GenerateLocalEnemyFor(string placeName)
{
switch (placeName)
{
case "swamp": return new Gator();
case "starbucks":
case "family reunion": return new FamilyReunionFactory(_randomizer).GetEnemy(_difficultyLevel);
case "middleEarth": return new Dragon();
case "texas truck stop": return new ChuckNorris();
default: return new HouseFly();
}
}

Notice that instead of directly instantiating an enemy when we’re at the family reunion, we delegate that task to our newly created factory. Let’s make a factory for each place now so that we can remove that awkward GetEnemy call and keep this method clean. In order to do this and return a factory instead of an enemey, we’re also going to need to make these factories polymorphic cousins of one another, by defining an interface (could also be an abstract base, which is less decoupled but allows implementation of a common constructor).

public interface IFamilyReunionFactory
{
Enemy GetEnemy(int difficultyLevel);
}

And, with that in place and all of the other factories defined (elided), here is the new narrative class:

public class GameNarrative
{
private readonly IRandomizeThings _randomizer;

private readonly int _difficultyLevel;

public GameNarrative(IRandomizeThings randomizer, int difficultyLevel)
{
_randomizer = randomizer;
_difficultyLevel = difficultyLevel;
}

public void MoveMainCharacterTo(string placeName)
{
var enemyFactory = GetEnemyFactory(placeName);
var enemy = enemyFactory.GetEnemy(_difficultyLevel);
InteractWithEnemy(enemy);
}

private IEnemyFactory GetEnemyFactory(string placeName)
{
switch (placeName)
{
case "swamp": return new SwampFactory(_randomizer);
case "starbucks": return new StarbucksFactory(_randomizer);
case "family reunion": return new FamilyReunionFactory(_randomizer);
case "middleEarth": return new MiddleEarthFactory(_randomizer);
case "texas truck stop": return new TexasTruckStopFactory(_randomizer);
default: return new DefaultFactory(_randomizer);
}
}

private void InteractWithEnemy(Enemy enemy)
{
Console.Write(enemy.Attack());
}
}

That’s looking pretty darn legible now. But it’s not just that the code is easy to read or even that it’s separated into factored methods and classes. The important thing here is conformance to SRP and the fact that it’s easy to find what needs to change and change it independently of other concerns. Think back to the change request that broke our spirit earlier. Adding new enemies? Piece of cake — just add classes for them and then add them to the random generation in the factories that are eligible to generate them. Porting enemy generation? Just make the GetEnemyGeneration method (or some variant of it) publicly accessible and call it elsewhere. All of the new enemy generation business rules? Put them in their appropriate factories. Cross cutting rules? Create a base factory class. These tasks are now quite manageable.

A More Official Explanation

The stated purpose of the Factory Method design pattern (from dofactory) is:

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

This creational pattern is also sometimes referred to as “virtual constructor” because of the way it separates the promise of object creation from the implementation via polymorphism. Be it an interface or abstract base class, the abstract definition defines a contract for the generation of polymorphic entities and then delegates that work to implementers/inheritors.

This has the powerful benefit of allowing flexibility and following of the open/closed principle not just for creation of objects but for strategies for object creation. In our example above, the IEnemyFactory is the Creator, the various factories are the Concrete Creators and the enemies are Products. We have the ability with this implementation to seamlessly add new enemies but also to seamlessly add new schemes for generating enemies. If we wanted to add a location called “mountains” with its own unique set of denizens to the game, this would be straightforward and have nearly 0 bearing on existing code.

It is worth noting the conceptual similarity to Abstract Factory at this point and pointing out that the jump from Factory Method to Abstract Factory is just the addition of more polymorph families. For instance, if each location had enemies, terrain, and allies, Abstract Factory would be a good fit. That said, the transition from Factory Method to Abstract Factory is extremely violent to the code base since the addition of methods to the factory require changes to all implementers. Thus it is probably good to spend some effort up front reasoning about what the factory should do, particularly if the concrete factories are spread far and wide (unless you are using an abstract base class and then there is some reprieve here as you can specify default behavior).

Other Quick Examples

  1. An enterprise application capable of pulling information from multiple persistence models (factory methods to create DAOs).
  2. A GUI intensive application that generates controls/forms/pages on the fly depending on user interaction.

A Good Fit – When to Use

This is an interesting one circa 2012 because it seems like a decent amount of the heavy lifting that I used to see this pattern do has been replaced by IoC containers or plugin architectures. In other words, the Gang of Four made it fashionable to move complex instance creation into its own place in your code, and the Unit Test/TDD crowd later made it fashionable to move it out of your code altogether. It’s also been squeezed on the other side, so to speak, by the prevalence of the “poor man’s factory method” — a simple static method that returns polymorphs representing a common interface or base class.

But in reality, this pattern has its own niche not covered by either of these situations. IoC containers and, to some extent, plugin architectures are really about decisions made at application start time. The point of abstracting them out of the codebase is to allow application behavior to be changed without rebuilding and re-deploying. Factory Method as I would advocate covers a subtly different usage scenario wherein the polymorphic type is not known at application startup. An obvious example (and the one we covered in this post) is where the user supplies input that governs which object should be created in some way.

But this could still mean using the static method rather than the class hierarchy of Factory Method. I would recommend the latter specifically in situations where the logic surrounding instance creation is more complex than switching over a simple argument or two and/or likely to grow and change with time (the aforementioned Open/Closed Principle). If you find that you have a static factory method that’s ballooning in size and cyclomatic complexity it’s probably time to consider a factory method hierarchy.

Square Peg, Round Hole – When Not to Use

The inverse of various situations described in the previous section is a good place to start. You probably don’t want to use this pattern for very simple scenarios (say, switching over an enum or character to create instances) and you probably don’t want to use it for decision that can be made prior to runtime as that introduces more complexity and indirection to your application than necessary. Another place that you’d avoid this is when you need an abstract factory because you’re creating object families.

As always, YAGNI applies, and factories are sort of iconic in representing over-engineering in OOP. I once heard a cynical but funny quote (don’t recall who originally said it, but if you know, please comment): “some people think they’ll use java to solve their problems — now they have a problem factory.” This is obviously tongue in cheek, but the implied point about pattern happy enterprise development shines through. It’s easy to get pretty elaborate when abstracting instance creation out of plumbing and service code (and I love the practice) but there’s a fine line between this and creating too many levels of indirection. Be careful that you actually need these factories and aren’t just speculatively abstracting. As a rule of thumb, I’d say that you should be able to look at them and think “man, it’s a good thing I pulled that into a class.”

So What? Why is this Better?

As show in the example, when judiciously used, the Factory Method pattern can transform what would have been a snarl of instantiation spaghetti into a well separated, maintainable set of classes. The “after” in this picture shows code that conforms to established OOP principles such as the Open/Closed Principle and the Single Responsibility Principle (you can throw Liskov in there too since there’s a lot of polymorphism here).

Once this is in place, adding new target/product objects for creation is a segregated and approachable problem and adding new creation schemes becomes quite easy. It’s also straightforward to separate creation from use in your code as well, leading to a lot of architectural flexibility. And, properly applied, it’s a good mechanism for avoiding the bane of programming existence — copy and paste coding.

5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Chuck Bryan
11 years ago

Awesome article Erik: very clean example that looks like a lot of code that I have written. Once I start getting a bunch of nested “ifs” or “switches”, I know it is time to consider construction patterns.

Erik Dietrich
11 years ago
Reply to  Chuck Bryan

Thanks for reading and for the kind words. I definitely feel the same way — starting to have a lot of flow logic in instance creation flips the “time to rethink this” switch in my head.

trackback

[…] at runtime since your instance creation may depend on external factors (for instance, if you have factory methods). So reflection is a runtime way to understand what type you’re dealing […]

Timothy Boyce
Timothy Boyce
11 years ago

In the GetEnemy method of FamilyReunionFactory you are constructing several different enemies, of which only one will ever be used. I realize this is just an example, but that part doesn’t seem right to me.

Erik Dietrich
11 years ago
Reply to  Timothy Boyce

Valid point, though my main focus was on abstracting away as much as possible not relevant to the pattern. A cleaner approach might be to define a series of generic methods with different number of generic parameters, ala Func and Action, constrain it with new(), and have the random picker do the instantiating.