DaedTech

Stories about Software

By

Flyweight

Quick Information/Overview

Pattern Type Structural
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Easy

Image courtesy of dofactory

Up Front Definitions

  1. Client: Code that uses the flyweight implementation
  2. Concrete Flyweight: A class that actually implements the abstract class/interface flyweight.
  3. Extrinsic State: State that is not common to the flyweights and varies per instance.
  4. Flyweight: An interface that defines and exposes the extrinsic state.
  5. Flyweight Factory: Class used by clients to retrieve instances of the flyweights.
  6. Intrinsic State: State that is common across all flyweights of the same type.

The Problem

Most of these design patterns posts deal with compile-time problems brought about by painting oneself into a corner with design decisions. In other words, if you make certain missteps when designing a system, it becomes rigid and difficult to change in the future. Patterns such as the Factories, Composite, Decorator, etc., all address prevention of such missteps by isolating responsibilities and making change management simple. Today, the problem we’re going to look at is a runtime problem rather than a compile-time problem.

Let’s say that you’re asked to create a model that simulates the distribution of mail in the USA for a given day. You start by establishing some pretty reasonable business objects to represent the domain concepts in question: letters and postcards. Each of these things has certain properties you’re going to need to keep track of, such as dimensions and postage, so that you can report in aggregate on paper usage, revenues, etc. Here is your first crack at business objects:

public abstract class MailPiece
{
    public abstract decimal Postage { get; set; }
    public abstract decimal Width { get; set; }
    public abstract decimal Height { get; set; }
    public abstract decimal Thickness { get; set; }
 
    public int DestinationZip { get; set; }
}
public class Letter : MailPiece 
{
    public override decimal Postage { get; set; }
    public override decimal Width { get; set; }
    public override decimal Height { get; set; }
    public override decimal Thickness { get; set; }
 
    public Letter()
    {
        Postage = 0.46M;
        Width = 11.5M;
        Height = 6.125M;
        Thickness = 0.25M;
    }
}
public class Postcard : MailPiece
{
    public override decimal Postage { get; set; }
    public override decimal Width { get; set; }
    public override decimal Height { get; set; }
    public override decimal Thickness { get; set; }
 
    public Postcard()
    {
        Postage = 0.33M;
        Width = 6.0M;
        Height = 4.25M;
        Thickness = 0.016M;
    }
}

Alright, awesome. Now, according to the USPS, there are 563 million mail pieces processed in the USA each day (as of 2011). So, let’s just use that as our loop counter, and off we’ll go:

static void Main(string[] args)
{
    var pieces = new List();
    for (long index = 0; index < 563000000; index++)
    {
        pieces.Add(new Letter() { DestinationZip = (int)(index % 100000) });
    }
 
    Console.ReadLine();
}

Satisfied, you fire up the program to make sure everything here is in good working order--although, really, why bother? I mean, what could possibly go wrong? The program chugs along for a bit, and it strikes you that it's taking a while and your desktop is starting to crawl. You fire up the process manager and see this:

Danger, Will Robinson

Yikes! That's... troubling. You start to wonder if maybe you should intervene and stop the program, but Visual Studio isn't being very responsive and you can't even seem to get it to hit a breakpoint. Just as you're contemplating drastic action, Visual Studio mercifully puts an end to things:

OutOfMemory

You're not very close to getting all of the records in, so you decide to divide the original 563 million by 24 in order to model the mail being processed on an hourly basis, but that's really all the more granular that you can do. You fire up the program again to run with 23,458,333 and hit out of memory once again.

So, What to Do?

If you look at your creation of letters (and presumably later, postcards) you should notice that there's a fair bit of waste here. For every letter you create, you're creating four decimals that are exactly the same for every letter, which means that you're storing four unnecessary decimals for all but one of the letters you create, which in turn means that you're storing somewhere in the neighborhood of two billion unnecessary decimal instances in memory. Whoah.

Let's try a different approach. What we really seem to want here is 23 and a half million zip codes and a single letter. So let's start off simply by building a list of that many zip codes and seeing what happens:

static void Main(string[] args)
{
    var pieces = new List();
    for (long index = 0; index < 23458333; index++)
    {
        pieces.Add(new Letter() { DestinationZip = (int)(index % 100000) });
    }
 
    Console.ReadLine();
}

Woohoo! That runs, and for the first time we have something that doesn't crash. But what we're really looking to do is cycle through all of those mail pieces, printing out their zip, postage, and dimensions. Let's start off by cheating:

static void Main(string[] args)
{
    var zipCodes = new List();
    var letter = new Letter();
    for (int index = 0; index < 23458333; index++)
    {
        zipCodes.Add(index % 100000);
        Console.Write(string.Format("Zip code is {0}, postage is {1} and height is {2}",
            zipCodes[index], letter.Postage, letter.Height));
    }
 
    Console.ReadLine();
}

That gets us what we want, but there's a lot of ugliness. The client class has to know about the exact mechanics of the mail piece's printing details, which is a no-no. It also has the responsibility for keeping track of the flyweight letter class. There are better candidates for both of these responsibilities. First of all, let's move the mechanism for printing information into the mail piece class itself.

public abstract class MailPiece
{
    public abstract decimal Postage { get; set; }
    public abstract decimal Width { get; set; }
    public abstract decimal Height { get; set; }
    public abstract decimal Thickness { get; set; }
 
    public string GetStatistics(int zipCode)
    {
        return string.Format("Zip code is {0}, postage is {1} and height is {2}",
            zipCode, Postage, Height);
    }
}

Notice that we've removed the settable "DestinationZip" and added a method that prints piece statistics, given a zip code. That allows us to simplify the client code:

static void Main(string[] args)
{
    var zipCodes = new List();
    var letter = new Letter();
    for (int index = 0; index < 23458333; index++)
    {
        zipCodes.Add(index % 100000);
        string pieceStatistics = letter.GetStatistics(zipCodes[index]);
        Console.Write(pieceStatistics);
    }
 
    Console.ReadLine();
}

Asking the letter object for its statistics definitely feels like a better approach. It's nice to get that bit out of the client implementation, particularly because it will now work for postcards as well and any future mail pieces that we decide to implement. But we're still worrying about instance management of the flyweights in the client class, which really doesn't care about them. Let's introduce a new class:

public class MailPieceFactory
{
    private readonly Dictionary _mailPieces = new Dictionary();
 
    public MailPiece GetPiece(char key)
    {
        if (!_mailPieces.ContainsKey(key))
            _mailPieces[key] = BuildPiece(key);
 
        return _mailPieces[key];            
    }
 
    private static MailPiece BuildPiece(char key)
    {
        switch (key)
        {
            case 'P': return new Postcard();
            default: return new Letter();
        }
    }
}

Here we have a public method called "GetPiece" to which we pass a key indicating what sort of piece we want. As far as client code goes, that's all that matters. Under the hood, we're managing the actual flyweights. If the dictionary doesn't have key we're interested in, we build a piece for that key. If it does, we simply return the flyweight from the hash. (Note that the scheme of indexing them by characters will scale, but isn't really optimal at the moment--you could use an enumeration here, restrict the set of allowed keys with preconditions, or have a special default scheme.)

Let's see what the client code looks like.

static void Main(string[] args)
{
    var factory = new MailPieceFactory();
    var zipCodes = new List();
 
    for (int index = 0; index < 23458333; index++)
    {
        zipCodes.Add(index % 100000);
        var randomPiece = factory.GetPiece(GetRandomKey());
        string pieceStatistics = randomPiece.GetStatistics(zipCodes[index]);
        Console.Write(pieceStatistics);
    }
 
    Console.ReadLine();
}
 
private static char GetRandomKey()
{
    return new Random().Next() % 2 == 0 ? 'P' : 'L';
}

There. Now the client code doesn't worry at all about keeping track of the flyweights or about how to format the statistics of the mail piece. It simply goes through a bunch of zip codes, creating random pieces for them, and printing out their details. (It could actually dispense with the list of zip codes, as implemented, but leaving them in at this point underscores the memory benefit of the flyweight pattern.)

There's now some nice extensibility here as well. If we implemented flats or parcels, it'd be pretty easy to accommodate. You'd just add the appropriate class and then amend the factory, and you'd be off and running. When dealing with scales of this magnitude, memory management is always going to be a challenge, so using a pattern up front that reuses and consolidates common information will be a big help.

A More Official Explanation

According to dofactory, the purpose of the Flyweight pattern is:

Use sharing to support large numbers of fine-grained objects efficiently.

The Flyweight pattern requires that you take the objects whose information you want to share for scaling purposes and divide their state into two categories: intrinsic and extrinsic. Intrinsic state is the state that will be shared across all instances of the same type of object, and extrinsic state is the state that will be stored outside of the instance containing common information. The reason for this division is to allow as much commonality as possible to be stored in a single object. In a way, it is reminiscent of simple class inheritance where as much common functionality as possible is abstracted to the base class. The difference here is that a single instance stores common information and an external interest holds the differences.

To make the most of the pattern, flyweight creation and management is abstracted into one class (the factory), intrinsic state to another set of classes (the concrete flyweights), and extrinsic state management to a third class (the client). Separating these concerns allows the client to incur only the memory overhead of the part of an object that varies while still reaping all of the benefits of OOP and polymorphism. This is a powerful optimization.

Other Quick Examples

  1. The iconic example of the Flyweight pattern is to have flyweights represent characters in a word processing document, with the extrinsic state of position in the document.
  2. Another use is rendering in graphical applications with many similar shapes or patterns on the screen in configurable locations.
  3. It can also be used to represent some fungible commodity of which there are many in a video game, such as enemies, soldiers, scenery elements, etc.
  4. One of the more interesting and practical examples is string "interning" in C#

A Good Fit – When to Use

As the cost of memory and disk space continues to plummet, emphasis on this pattern is seeming to wane a bit. However, there will always be occasions in which resource management and optimization are crucial, and bottlenecks will always exist where even liberally purchased resources need to be used wisely. The flyweight pattern is a good fit any time you have redundant, common state in many objects that you're creating. If you find yourself in this position, the pattern is really a no-brainer since it's simple and costs very little to implement in terms of code complexity.

Square Peg, Round Hole – When Not to Use

This isn't the kind of pattern where you're likely to go out looking for excuses to try it out since it solves a very specific problem that is different from a lot of other patterns. I would exercise caution more when choosing extrinsic and intrinsic state in that you're going to experience downstream pain if you label things "intrinsic" that actually can vary. Doing this threatens to break the pattern and the abstraction that you've created since modifying state that's categorized as intrinsic will mean that your flyweights are no longer interchangeable and you're going to start getting stuff wrong.

So this isn't a good fit if you don't have a good grasp yet on what should be extrinsic and what should be intrinsic. It's also a bad fit if all state is extrinsic, as then there is no gain from the pattern. Another potential misuse that's always worth mentioning with an optimization strategy is premature optimization. While I personally consider the elimination of duplication at runtime simply to be good design, I'd say that you might want to consider not bothering with the additional compile-time complexity if you're not going to have very many objects. If, for instance, you were simulating twenty pieces of mail instead of tens of millions, it might not be worth the additional complexity.

So What? Why is this Better?

This one pretty much sells itself. In the example above, you can run the code without crashing or altering your data structures. Generally speaking, this is a pattern that helps you reduce your application's memory footprint simply by creating a clever abstraction and shuffling the internal representation. If you can identify when there will be common information in volume, you can separate it from the unique information and make sure you're being as efficient as possible.

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.

By

Facade

Quick Information/Overview

Pattern Type Structural
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Easy

Up Front Definitions

The Problem

Let’s say that you work on a web based piece of software that processes orders for customers in some sort of retail capacity and that there is a framework for a lot of existing operations with which you have to deal. You’re tasked with creating the UI for taking orders from customers. At your disposal, you have three handy functionalities: an order DAO for storing order information to the database, a receipt printer for printing receipts, and an email sender for sending confirmation emails. These things exist in different assemblies and your presentation layer assembly, fortunately, has references to all of them.

So, you write some code that looks like this:

public class OrderViewModel
{
    private readonly EmailSender _emailSender;
    private readonly ReceiptPrinter _receiptPrinter;
    private readonly OrderDao _orderDao;

    public OrderViewModel(EmailSender emailSender, ReceiptPrinter receiptPrinter, OrderDao orderDao)
    {
        _emailSender = emailSender;
        _receiptPrinter = receiptPrinter;
        _orderDao = orderDao;
    }

    public void HandleOrderExecuted(Order order)
    {
        ExecuteOrder(order);
    }

    private void ExecuteOrder(Order order)
    {
        _orderDao.StoreOrder(order);
        _emailSender.SendEmail(new OrderEmail(order));
        _receiptPrinter.PrintReceiptForOrder(order);
    }
}

Life is good. Your customer can now issue an order through your page and the view model that supports it. Making note of your success, your manager hands you a requirement to display recommendations to the screen following an order. Luckily, there is a module called RecommendationEngine that you can use for just such an occasion:

public class OrderViewModel
{
    private readonly EmailSender _emailSender;
    private readonly ReceiptPrinter _receiptPrinter;
    private readonly OrderDao _orderDao;
    private readonly RecommendationEngine _recommendationEngine;

    public ObservableCollection Recommendations { get; set; }

    public OrderViewModel(EmailSender emailSender, ReceiptPrinter receiptPrinter, OrderDao orderDao, RecommendationEngine engine)
    {
        _emailSender = emailSender;
        _receiptPrinter = receiptPrinter;
        _orderDao = orderDao;
        _recommendationEngine = engine;
        Recommendations = new ObservableCollection();
    }

    public void HandleOrderExecuted(Order order)
    {
        ExecuteOrder(order);
    }

    private void ExecuteOrder(Order order)
    {
        _orderDao.StoreOrder(order);
        _emailSender.SendEmail(new OrderEmail(order));
        _receiptPrinter.PrintReceiptForOrder(order);

        PouplateRecommendations();
    }

    private void PouplateRecommendations()
    {
        Recommendations.Clear();
        foreach (var myRecommendation in _recommendationEngine.GetRecommendations())
            Recommendations.Add(myRecommendation);
    }
}

Excellent. Well, mostly, anyway. This class’s constructor is starting to get a little busy and it depends on sort of a hodgepodge of other assemblies. But, it’s probably nothing — adding that additional assembly reference for the recommendation engine was probably just an anomaly.

Besides, your manager is so impressed that it’s time to assign you to a different screen. As it turns out, there is the traditional order placement screen and a new express one for frequent customers. So, you need to write a new screen and ViewModel, which you do. Since you’ve already implemented the order execution logic, you just copy and paste it and the field declarations into the new ViewModel, initializing the fields in the constructor. You’re not thrilled about the copy and paste, but whatcha gonna do?

At this point, your manager points out a requirement that nobody had considered: users might want to access a virtual copy of their receipts later. You notice an assembly containing a class called ReceiptDao that sounds promising, and you add that:

public class OrderViewModel
{
    private readonly EmailSender _emailSender;
    private readonly ReceiptPrinter _receiptPrinter;
    private readonly OrderDao _orderDao;
    private readonly ReceiptDao _receiptDao;
    private readonly RecommendationEngine _recommendationEngine;

    public ObservableCollection Recommendations { get; set; }

    public OrderViewModel(EmailSender emailSender, ReceiptPrinter receiptPrinter, OrderDao orderDao, RecommendationEngine engine, ReceiptDao receiptDao)
    {
        _emailSender = emailSender;
        _receiptPrinter = receiptPrinter;
        _orderDao = orderDao;
        _recommendationEngine = engine;
        _receiptDao = receiptDao;
        Recommendations = new ObservableCollection();
    }

    public void HandleOrderExecuted(Order order)
    {
        ExecuteOrder(order);
    }

    private void ExecuteOrder(Order order)
    {
        _orderDao.StoreOrder(order);
        _emailSender.SendEmail(new OrderEmail(order));
        _receiptPrinter.PrintReceiptForOrder(order);
        _receiptDao.Save(order);

        PouplateRecommendations();
    }

    private void PouplateRecommendations()
    {
        Recommendations.Clear();
        foreach (var myRecommendation in _recommendationEngine.GetRecommendations())
            Recommendations.Add(myRecommendation);
    }
}

Well, problem solved, though that dependency list is growing. The order logic now stores the receipt. You promote it and get a defect back from QA that the express ordering system doesn’t store virtual receipts the way the normal one does. Oops. Such is life when you copy and paste program — you forgot to change the other implementation. Ah, well, happens to the best of us.

But now, you get a series of assignments from the manager to add more functionality from other modules while simultaneously adding more places from which an order can be placed. That means adding a lot of code to the two implementations that already exist, bloating them, and then copying and pasting the resulting monstrosity to various other locations.

So, What to Do?

As always in this section, it’s important to identify where things went wrong. It’s debatable as to whether adding that fourth dependency was a problem or not — that constructor is getting pretty busy at this point and the dependency fan out is climbing. However, in and of itself, that may not be a problem.

It stops being debatable (as it always does) when they copying and pasting starts. That’s bad. Any time you find yourself doing that you’re failing at design. In this case, the most obvious fix is the one that will lead us to a better path. Specifically, we need to factor the duplicated code into a class. So, let’s introduce a class called OrderService:

public class OrderService
{
    private readonly EmailSender _emailSender;
    private readonly ReceiptPrinter _receiptPrinter;
    private readonly OrderDao _orderDao;
    private readonly ReceiptDao _receiptDao;
    private readonly RecommendationEngine _recommendationEngine;

    public OrderService(EmailSender emailSender, ReceiptPrinter receiptPrinter, OrderDao orderDao, ReceiptDao receiptDao, RecommendationEngine recommendationEngine)
    {
        _emailSender = emailSender;
        _receiptPrinter = receiptPrinter;
        _orderDao = orderDao;
        _receiptDao = receiptDao;
        _recommendationEngine = recommendationEngine;
    }

    public void ExecuteOrder(Order order)
    {
        _orderDao.StoreOrder(order);
        _emailSender.SendEmail(new OrderEmail(order));
        _receiptPrinter.PrintReceiptForOrder(order);
        _receiptDao.Save(order);
    }

    public IEnumerable GetRecommendations()
    {
        return _recommendationEngine.GetRecommendations();
    }
}

Now, this service class can be used by any ViewModel client without duplicating logic. Here’s what the client now looks like:

public class OrderViewModel
{
    private readonly OrderService _service;

    public ObservableCollection Recommendations { get; set; }

    public OrderViewModel(OrderService service)
    {
        _service = service;
        Recommendations = new ObservableCollection();
    }

    public void HandleOrderExecuted(Order order)
    {
        _service.ExecuteOrder(order);
        PouplateRecommendations();
    }

    private void PouplateRecommendations()
    {
        Recommendations.Clear();
        foreach (var myRecommendation in _service.GetRecommendations())
            Recommendations.Add(myRecommendation);
    }
}

The only duplication that might occur here is injecting and invoking the service (though that can be fixed among the ViewModels, but that’s beyond the scope of this post). We’ve eliminated the duplication that makes things like adding the receipt storage a pain point. Also, observe that if we put the service in a separate assembly from the ViewModels, we can now remove the assembly references to the various lower level services such as EmailSender, ReceiptPrinter, etc.

While this separation may seem like pushing our problems out a layer, there is a real benefit to doing this. Specifically, presentation layer classes should not be concerned with locating lower level components. They should be allowed to focus on marshaling data for presentation. Following the single responsibility principle suggests that presenting order confirmation to the user and navigating the mechanics of the subsystems required for an order are two separate responsibilities.

The five (and growing) dependencies that have been added to the constructor of the service to spare the ViewModel are still problematic in terms of good design. This could be fixed with further facades, if the application is large enough to support conceptual sub-layers. That is, there could be a general DAO facade and a general externalities facade that took care of the dao functions and email/receipts/recommendations respectively. This scheme would have the service knowing only about two collaborators instead of five while deepening the call stack hierarchy.

Another approach might be to consolidate some of these assemblies or classes at lower layers, if possible. It might also be reasonable, depending on the situation, simply to leave this service class alone, having abstracted this sub-system out of the presentation layer.

A More Official Explanation

DoFactory defines Facade as a pattern that aims to:

Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.

This is pretty straightforward to understand and it constitutes one of the most basic and fundamental patterns of programming. Facades provide a layer of abstraction, hiding low level details from client code in favor of broader, easier to understand interactions. I have blogged extensively about the subject of abstraction, if you’d like a more in-depth treatment of the concept.

In general, facades form the back bone of solid architecture in code bases by virtue of hiding conceptually difficult details behind conceptually simple points of access. The crux of this pattern is hiding and managing complexity.

Other Quick Examples

Other incarnations of the Facade Pattern include:

  1. The iconic example of mortgage applications where lenders, banks, inspectors, etc are all necessary to complete the single process.
  2. A unified or single class that you write to hide an ugly third-party API or series of APIs.
  3. In a very real sense, the structure of a class is a bit of a facade since implementation details (private fields and members) are hidden behind the facade of the public API.

A Good Fit – When to Use

Facade is good any time you want to hide details of a process from client code. This can apply, as I mentioned, at the assembly/module level and it can even apply at the class and method level. If you practice good software design this is a pattern that you will find yourself using constantly. It is the essence of providing good abstractions.

Square Peg, Round Hole – When Not to Use

The main usage anti-pattern of a facade is providing a layer or “wrapper” that really does nothing or fails to simplify things for clients. There can be a fine line between organizing code and hiding details and introducing pointless layering, so it is important to consider whether the facade that you’re adding is either (1) making things easier or (2) hiding details that should be hidden. If it’s doing neither of these things, it probably shouldn’t exist.

So What? Why is this Better?

Generally speaking, facades can help eliminate redundant logic and they can simplify interaction with a system. These are two of the most important considerations in all of software. Redundancy is the bane of maintainability and abstraction is the backbone of understandable systems. Well placed facades (such as layered architecture, for instance) provide both in one shot. The end result is that your code will be well factored and decoupled, easy to maintain, and easy to reason about.

By

Decorator

Quick Information/Overview

Pattern Type Structural
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Easy

Up Front Definitions

  1. Decorator: An object that is both an inherits from and operates on another object.
  2. Component: Abstract target base class (or interface) of the decorator pattern.
  3. Target: For the purposes of this post, I use this term interchangeably with Component.

The Problem

Let’s say that you have to model employees at a company, and all employees have a name, an hourly wage, and a bio that describes them. Furthermore, these items are going to be determined by the type of employee that each employee is (they can be Workers, Managers, or Executives for now, but there might be more later). Since this begs for an extensible, polymorphic structure, you create the following class structure and program to take it for a test drive:
Read More

By

Composite

Quick Information/Overview

Pattern Type Structural
Applicable Language/Framework Agnostic OOP
Pattern Source Gang of Four
Difficulty Easy

Up Front Definitions

  1. Component: This is the abstract object that represents any and all members of the pattern
  2. Composite: Derives from component and provides the definition for the class that contains other components
  3. Leaf: A concrete node that encapsulates data/behavior and is not a container for
    other components.
  4. Tree: For our context here, tree describes the structure of all of the components.

The Problem

Let’s say that you get a call in to write a little console application that allows users to make directories, create empty files, and delete the same. The idea is that you can create the whole structure in memory and then dump it to disk in one fell swoop. Marketing thinks this will be a hot seller because it will allow users to avoid the annoyance of disk I/O overhead when planning out a folder structure (you might want to dust off your resume, by the way).

Simple enough, you say. For the first project spring, you’re not going to worry about sub-directories – you’re just going to create something that will handle files and some parent directory.

So, you create the following class (you probably create it with actual input validation, but I’m trying to stay focused on the design pattern):

public class DirectoryStructure
{
    private const string DefaultDirectory = ".";

    private readonly List _filenames = new List();

    private string _directory = DefaultDirectory;

    public string RootDirectory { get { return _directory; } set { _directory = string.IsNullOrEmpty(value) ? DefaultDirectory : value; } }

    public void AddFile(string filename)
    {
        _filenames.Add(filename);
        _filenames.Sort();
    }

    public void DeleteFile(string filename)
    {
        if (_filenames.Contains(filename))
        {
            _filenames.Remove(filename);
        }
    }

    public void PrintStructure()
    {
        Console.WriteLine("Starting in " + RootDirectory);
        _filenames.ForEach(filename => Console.WriteLine(filename));
    }

    public void CreateOnDisk()
    {
        if (!Directory.Exists(RootDirectory))
        {
            Directory.CreateDirectory(RootDirectory);
        }

        _filenames.ForEach(filename => File.Create(filename));
    }
}

Client code is as follows:

static void Main(string[] args)
{
    var myStructure = new DirectoryStructure();

    myStructure.AddFile("file1.txt");
    myStructure.AddFile("file2.txt");
    myStructure.AddFile("file3.txt");
    myStructure.DeleteFile("file2.txt");

    myStructure.PrintStructure();

    Console.Read();

    myStructure.CreateOnDisk();
}

That’s all well and good, so you ship and start work on sprint number 2, which includes the story that users want to be able to create one level of sub-directories. You do a bit of refactoring, deciding to make root a constructor parameter instead of a settable property, and then get to work on this new story.

You wind up with the following:

public class DirectoryStructure
{
    private const string DefaultDirectory = ".";

    private readonly List _filenames = new List();
    private readonly List _directories = new List();
    private readonly Dictionary> _subDirectoryFilenames = new Dictionary>();

    private readonly string _root;

    public DirectoryStructure(string root = null)
    {
        _root = string.IsNullOrEmpty(root) ? DefaultDirectory : root;
    }


    public void AddFile(string filename)
    {
        _filenames.Add(filename);
        _filenames.Sort();
    }

    public void AddFile(string subDirectory, string filename)
    {
        if (!_directories.Contains(subDirectory))
        {
            AddDirectory(subDirectory);
        }
        _subDirectoryFilenames[subDirectory].Add(filename);
    }

    public void AddDirectory(string directoryName)
    {
        _directories.Add(directoryName);
        _subDirectoryFilenames[directoryName] = new List();
    }

    public void DeleteDirectory(string directoryName)
    {
        if (_directories.Contains(directoryName))
        {
            _directories.Remove(directoryName);
            _subDirectoryFilenames[directoryName] = null;
        }
    }

    public void DeleteFile(string filename)
    {
        if (_filenames.Contains(filename))
        {
            _filenames.Remove(filename);
        }
    }

    public void DeleteFile(string directoryName, string filename)
    {
        if (_directories.Contains(directoryName) && _subDirectoryFilenames[directoryName].Contains(filename))
        {
            _subDirectoryFilenames[directoryName].Remove(filename);
        }
    }

    public void PrintStructure()
    {
        Console.WriteLine("Starting in " + _root);
        foreach (var myDir in _directories)
        {
            Console.WriteLine(myDir);
            _subDirectoryFilenames[myDir].ForEach(filename => Console.WriteLine("\t" + filename));
        }
        _filenames.ForEach(filename => Console.WriteLine(filename));
    }

    public void CreateOnDisk()
    {
        if (!Directory.Exists(_root))
        {
            Directory.CreateDirectory(_root);
        }

        foreach (var myDir in _directories)
        {
            Directory.CreateDirectory(Path.Combine(_root, myDir));
            _subDirectoryFilenames[myDir].ForEach(filename => File.Create(Path.Combine(myDir, filename)));
        }
        _filenames.ForEach(filename => File.Create(filename));
    }
}

and client code:

static void Main(string[] args)
{
    var myStructure = new DirectoryStructure();

    myStructure.AddFile("file1.txt");
    myStructure.AddDirectory("firstdir");
    myStructure.AddFile("firstdir", "hoowa");
    myStructure.AddDirectory("seconddir");
    myStructure.AddFile("seconddir", "hoowa");
    myStructure.DeleteDirectory("seconddir");
    myStructure.AddFile("file2.txt");
    myStructure.AddFile("file3.txt");
    myStructure.DeleteFile("file2.txt");

    myStructure.PrintStructure();

    Console.Read();

    myStructure.CreateOnDisk();
}

Yikes. That’s starting to smell. You’ve had to add overloads for adding file and deleting file, add methods for add/delete directory, and append logic to print and create. Basically, you’ve had to either touch or overload every method in the class. Generally, that’s a surefire sign that you’re doin’ it wrong. But, no time for that now because here comes the third sprint. This time, the business wants two levels of nesting. So, you get started and you see just how ugly things are going to get. I won’t provide all of your code here so that the blog can keep a PG rating, but here’s the first awful thing that you had to do:

private readonly List _filenames = new List();
private readonly List _directories = new List();
private readonly Dictionary> _subDirectoryFilenames = new Dictionary>();
private readonly Dictionary> _subDirectoryNames;
private readonly Dictionary>> _subSubDirectoryFilenames = new Dictionary>>();

You also had to modify or overload every method yet again, bringing the method total to 12 and the complexity of each method to a larger figure. You’re pretty sure you can’t keep this up for an arbitrary number of sprints, so you send out your now-dusted off resume and foist this stinker on the hapless person replacing you.

So, What to Do?

What went wrong here is relatively easy to trace. Let’s backtrack to the start of the second sprint when we needed to support sub-directories. As we’ve seen in some previous posts in this series, the first foray at implementing the second sprint gives off the code smell, primitive obsession. This is a code smell wherein bunches of primitive types (string, int, etc) are used in ad-hoc fashion to operate as some kind of ad-hoc class.

In this case, the smell is coming from the series of lists and dictionaries centering around strings to represent file and directory names. As the sprints go on, it’s time to recognize that there is a need for at least one class here, so let’s create it and call it “SpeculativeDirectory” (so as not to confuse it with the C# Directory class).

public class SpeculativeDirectory
{
    private const string DefaultDirectory = ".";

    private readonly HashSet _subDirectories = new HashSet();

    private readonly HashSet _files = new HashSet();

    private readonly string _name = string.Empty;
    public string Name { get { return _name; } }

    public SpeculativeDirectory(string name)
    {
        _name = string.IsNullOrEmpty(name) ? DefaultDirectory : name;
    }

    public SpeculativeDirectory GetDirectory(string directoryName)
    {
        return _subDirectories.FirstOrDefault(dir => dir.Name == directoryName);
    }

    public string GetFile(string filename)
    {
        return _files.FirstOrDefault(file => file == filename);
    }

    public void Add(string file)
    {
        if(!string.IsNullOrEmpty(file))
            _files.Add(file);
    }

    public void Add(SpeculativeDirectory directory)
    {
        if (directory != null && !string.IsNullOrEmpty(directory.Name))
        {
            _subDirectories.Add(directory);
        }
    }

    public void Delete(string file)
    {
        _files.Remove(file);
    }

    public void Delete(SpeculativeDirectory directory)
    {
        _subDirectories.Remove(directory);
    }

    public void PrintStructure(int depth)
    {
        string myTabs = new string(Enumerable.Repeat('\t', depth).ToArray());
        Console.WriteLine(myTabs + Name);

        foreach (var myDir in _subDirectories)
        {
            myDir.PrintStructure(depth + 1);
        }
        foreach (var myFile in _files)
        {
            Console.WriteLine(myTabs + "\t" + myFile);
        }
    }

    public void CreateOnDisk(string path)
    {
        string myPath = Path.Combine(path, Name);

        if (!Directory.Exists(myPath))
        {
            Directory.CreateDirectory(myPath);
        }

        _files.ToList().ForEach(file => File.Create(Path.Combine(myPath, file)));
        _subDirectories.ToList().ForEach(dir => dir.CreateOnDisk(myPath));
    }

}

And, the DirectoryStructure class is now:

public class DirectoryStructure
{
    private readonly SpeculativeDirectory _root;

    public DirectoryStructure(string root = null)
    {
        _root = new SpeculativeDirectory(root);
    }


    public void AddFile(string filename)
    {
        _root.Add(filename);
    }

    public void AddFile(string directoryName, string filename)
    {
        var myDirectory = _root.GetDirectory(directoryName);
        if (myDirectory != null)
        {
            myDirectory.Add(filename);
        }
    }

    public void AddDirectory(string directoryName)
    {
        _root.Add(new SpeculativeDirectory(directoryName));
    }

    public void DeleteFile(string filename)
    {
        _root.Delete(filename);
    }

    public void DeleteFile(string directoryName, string filename)
    {
        var myDirectory = _root.GetDirectory(directoryName);
        if (myDirectory != null)
        {
            myDirectory.Delete(filename);
        }
    }

    public void DeleteDirectory(string directoryName)
    {
        _root.Delete(directoryName);
    }

    public void PrintStructure()
    {
        _root.PrintStructure(0);
    }

    public void CreateOnDisk()
    {
        _root.CreateOnDisk(string.Empty);
    }
}

The main program that invokes this class is unchanged. So, now, notice the Structure of SpeculativeDirectory. It contains a collection of strings, representing files, and a collection of SpeculativeDirectory, representing sub-directories. For things like PrintStructure() and CreateOnDisk(), notice that we’re now taking advantage of recursion.

This is extremely important because what we’ve done here is future proofed for sprint 3 much better than before. It’s still going to be ugly and involve more and more overloads, but at least it won’t require defining increasingly nested (and insane) dictionaries in the DirectoryStructure class.

Speaking of DirectoryStructure, does this class serve a purpose anymore? Notice that the answer is “no, not really”. It basically defines a root directory and wraps its operations. So, let’s get rid of that before we do anything else.

To do that, we can just change the client code to the following and delete DirectoryStructure:

static void Main(string[] args)
{
    var myDirectory = new SpeculativeDirectory(".");
    myDirectory.Add("file1.txt");
    myDirectory.Add(new SpeculativeDirectory("firstdir"));
    myDirectory.GetDirectory("firstdir").Add("hoowa");
    var mySecondDir = new SpeculativeDirectory("seconddir");
    myDirectory.Add(mySecondDir);
    myDirectory.GetDirectory("seconddir").Add("hoowa");
    myDirectory.Delete(mySecondDir);
    myDirectory.Add("file2.txt");
    myDirectory.Add("file3.txt");
    myDirectory.Delete("file2.txt");

    myDirectory.PrintStructure(0);

    Console.Read();

    myDirectory.CreateOnDisk(".");

}

Now, we’re directly using the directory object and we’ve removed a class in addition to cleaning things up. The API still isn’t perfect, but we’re gaining some ground. So, let’s turn our attention now to cleaning up SpeculativeDirectory. Notice that we have a bunch of method pairs: GetDirectory/GetFile, Add(Directory)/Add(string), Delete(Directory)/Delete(string). This kind of duplication is a code smell — we’re begging for polymorphism here.

Notice that we are performing operations routinely on SpeculativeDirectory and performing the same operations on the string representing a file. It is worth noting that if we had a structure where file and directory inherited from a common base or implemented a common interface, we could perform operations on them just once. And, as it turns out, this is the crux of the command pattern.

Let’s see how that looks. First, we’ll define a SpeculativeFile object:

public class SpeculativeFile
{
    private readonly string _name;
    public string Name { get; }

    public SpeculativeFile(string name)
    {
        _name = name ?? string.Empty;
    }

    public void Print(int depth)
    {
        string myTabs = new string(Enumerable.Repeat('\t', depth).ToArray());
        Console.WriteLine(myTabs + Name);
    }

    public void CreateOnDisk(string path)
    {
        File.Create(Path.Combine(path, _name));
    }
}

This is pretty simple and straightforward. The file class knows how to print itself and how to create itself on disk, and it knows that it has a name. Now our task is to have a common inheritance model for file and directory. We’ll go with an abstract base class since they are going to have common implementations and file won’t have an implementation, per se, for add and delete. Here is the common base:

public abstract class SpeculativeComponent
{
    private readonly string _name;
    public string Name { get { return _name; } }

    private readonly HashSet _children = new HashSet();
    protected HashSet Children { get { return _children; } }

    public SpeculativeComponent(string name)
    {
        _name = name ?? string.Empty;
    }

    public virtual SpeculativeComponent GetChild(string name) { return null; }

    public virtual void Add(SpeculativeComponent component) { }

    public virtual void DeleteByName(string name) { }

    public void Print()
    {
        Print(0);
    }

    public void CreateOnDisk()
    {
        CreateOnDisk(Name);
    }

    protected virtual void Print(int depth)
    {
        string myTabs = new string(Enumerable.Repeat('\t', depth).ToArray());
        Console.WriteLine(myTabs + Name);

        foreach (SpeculativeComponent myChild in _children)
        {
            myChild.Print(depth + 1);
        }
    }

    protected virtual void CreateOnDisk(string path)
    {
        foreach (var myChild in _children)
        {
            myChild.CreateOnDisk(Path.Combine(path, Name));
        }
    }
        
}

A few things to note here. Fist of all, our recursive Print() and CerateOnDisk() methods are divided into two methods each, one public, one private. This is continue to allow for recursive calls but without awkwardly forcing the user to pass in zero or empty or whatever for path/depth. Notice also that common concerns for the two different types of nodes (file and directory) are now here, some stubbed as do-nothing virtuals and others implemented. The reason for this is conformance to the pattern — while files and directories share some overlap, some operations are clearly not meaningful for both (particularly adding/deleting and anything else regarding children). So, you do tend to wind up with the leaves (SpeculativeFile) ignoring inherited functionality, this is generally a small price to pay for avoiding duplication and the ability to recurse to n levels.

With this base class, we have pulled a good bit of functionality out of the file class, which is now this:

public class SpeculativeFile : SpeculativeComponent
{
    public SpeculativeFile(string name) : base(name) {}

    protected override void CreateOnDisk(string path)
    {
        File.Create(Path.Combine(path, Name));
        base.CreateOnDisk(path);
    }
}

Pretty simple. With this new base class, here is new SpeculativeDirectory class:

public class SpeculativeDirectory : SpeculativeComponent
{
    public SpeculativeDirectory(string name) : base(name) { }

    public override SpeculativeComponent GetChild(string name)
    {
        return Children.FirstOrDefault(child => child.Name == name);
    }

    public override void Add(SpeculativeComponent child)
    {
        if(child != null)
            Children.Add(child);
    }

    public override void DeleteByName(string name)
    {
        var myMatchingChild = Children.FirstOrDefault(child => child.Name == name);
        if (myMatchingChild != null)
        {
            Children.Remove(myMatchingChild);
        }
    }

    protected override void CreateOnDisk(string path)
    {
        string myPath = Path.Combine(path, Name);
        if (!Directory.Exists(myPath))
        {
            Directory.CreateDirectory(myPath);
        }

        base.CreateOnDisk(path);
    }
}

Wow. A lot more focused and easy to reason about, huh? And, finally, here is the new API:

static void Main(string[] args)
{
    var myDirectory = new SpeculativeDirectory(".");
    myDirectory.Add(new SpeculativeFile("file1.txt"));
    myDirectory.Add(new SpeculativeDirectory("firstdir"));
    myDirectory.GetChild("firstdir").Add(new SpeculativeFile("hoowa"));
    myDirectory.Add(new SpeculativeDirectory("seconddir"));
    myDirectory.GetChild("seconddir").Add(new SpeculativeFile("hoowa"));
    myDirectory.DeleteByName("seconddir");
    myDirectory.Add(new SpeculativeFile("file2.txt"));
    myDirectory.Add(new SpeculativeFile("file3.txt"));
    myDirectory.DeleteByName("file2.txt");

    myDirectory.Print();

    Console.Read();

    myDirectory.CreateOnDisk();

}

Even the API has improved since our start. We’re no longer creating this unnatural “structure” object. Now, we just create root directory and add things to it with simple API calls in kind of a fluent interface.

Now, bear in mind that this is not as robust as it could be, but that’s what you’ll do in sprint 3, since your sprint 2 implemented sub-directories for N depths of recursion and not just one. 🙂

A More Official Explanation

According to dofactory, the Composite Pattern’s purpose is to:

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

What we’ve accomplished in rescuing the speculative directory creation app is to allow the main program to perform operations on nodes in a directory tree without caring whether they are files or directories (with the exception of actually creating them). This is most evident in the printing and writing to disk. Whether we created a single file or an entire directory hierarchy, we would treat it the same for creating on disk and for printing.

The elegant concept here is that we can build arbitrarily large structures with arbitrary conceptual tree structures and do things to them uniformly. This is important because it allows the encapsulation of tree node behaviors within the objects themselves. There is no master object like the original DirectoryStructure that has to walk the tree, deciding how to treat each element. Any given node in the tree knows how to treat itself and its sub-elements.

Other Quick Examples

Other places where one might use the composite pattern include:

  1. GUI composition where GUI widgets can be actual widgets or widget containers (Swing java, WPF XAML, etc).
  2. Complex Chain of Responsibility structures where some nodes handle events and others simply figure out who to hand them over to
  3. A menu structure where nodes can either be actions or sub-menus.

A Good Fit – When to Use

The pattern is useful when (1) you want to represent an object hierarchy and (2) there is some context in which you want to be able to ignore differences between the objects and treat them uniformly as a client. This is true in our example here in the context of printing the structure and writing it to disk. The client doesn’t care whether something is a file or a directory – he just wants to be able to iterate over the whole tree performing some operation.

Generally speaking, this is good to use anytime you find yourself looking at a conceptual tree-like structure and iterating over the whole thing in the context of a control flow statement (if or case). In our example, this was achieved indirectly by different method overloads, but the result in the end would have been the same if we had been looking at a single method with a bit of logic saying “if node is a file, do x, otherwise, do y”.

Square Peg, Round Hole – When Not to Use

There are some subtle considerations here. You don’t want to use this if all of your nodes can be the same type of object, such as the case of some simple tree structure. If you were, for example, creating a sorted tree for fast lookup, where each node had some children and a payload, this would not be an appropriate use of composite.

Another time you wouldn’t want to use this is if a tree structure is not appropriate for representing what you want to do. If our example had not had any concept of recursion and were only for representing a single directory, this would not have been appropriate.

So What? Why is this Better?

The code cleanup here speaks for itself. We were able to eliminate a bunch of method overloads (or conditional branching if we had gone that way), making the code more maintainable. In addition, it allows elimination of a structure that rots as it grows — right out of the box, the composite pattern with its tree structure allows handling of arbitrarily deep and wide tree structures. And, finally, it allows clients to walk the tree structure without concerning themselves with what kind of nodes its processing and how to navigate to the next nodes.