Click here to Skip to main content
15,883,883 members
Articles / General Programming

Constructing the Factory Method Pattern

Rate me:
Please Sign up or sign in to vote.
4.95/5 (12 votes)
7 May 2013CPOL7 min read 29.3K   156   24   15
A Basic Implementation of the GoF Factory Method Pattern

Introduction

I hope to introduce a very basic implementation of the GoF design pattern. This is not intended to be the simplest possible implementation of the pattern ( a simpler one could certainly be derived from the Wikipedia entry on this topic http://en.wikipedia.org/wiki/Factory_method_pattern#Java). The intention is to attempt to demonstrate what the Factory Method Pattern is for, and give a simple implementation of it. This article will be relatively brief and hopefully clear for those trying to get to grips with this commonly mis-understood pattern.  

Please note, this is a short, beginner's article. By beginner I mean beginner to this design pattern, it is necessary that the reader understand basic inheritance (especially  interfaces) and visibility modifiers (principally internal and public). 

Background - What is the Factory Method Pattern For? 

I've seen the intent defined as "Given an interface for creating an object, but let subclasses decide which class to instantiate, then subclasses use factory methods. The factory method pattern lets a class defer instantiation to subclasses. "  Which is more a statement of what it does and not very clear unless you know why it does it in my opinion.  Let us start with first principles. In c-based languages (or at least those known to me at the time of writing) constructors:  

  • Can't be defined in an interface  
  • Must have their container type known to be called - both the type and the constructor must be visible to the calling code for MyType foo = new <code>MyType() to work   
Let us suppose we want to write a logging framework, and we need to create a hypothetical ILogger interface. With our framework, we are to supply two ILogger implementations FileLogger and SqlAndSql to represent two different logging destinations. Now suppose that we do not want allow the "client" code to have access to the concrete classes for some reason. In this case, the constructor cannot be defined in the interface so using ILogger will not work, and we can't call new on these classes directly as we have deliberately made them unavailable. So what do we do? An answer is to use the Factory Method Pattern. 

Creating the Pattern  

The Logging classes - creating the problem to be overcome.  

As described above we want to expose some logging functionality, step one is to create the ILogger interface. For simplicity, I'm going to define our Interface  as:   

C#
namespace LoggerClassLibrary
{
    public interface ILogger
    {
        string Log();
    }
}    

Nothing too complicated there. Now we want to create the two implementations of the interface mentioned earlier SqlLogger and DiskLogger. For this article I will provde a fake, stub implementation to keep the code simple, and so avoid distracting from the actual work of the article.  These classes are going to be: 

C#
namespace LoggerClassLibrary.ConcreteLoggers
{
    internal class SqlLogger : ILogger
    {
        public string Log()
        {
            return "Logging to SQL";
        }
    }
} 

 and 

C#
namespace LoggerClassLibrary.ConcreteLoggers
{
    internal class DiskLogger : ILogger
    {
        public string Log()
        {
            return "Logging to Disk";
        }
    }
}

Note that all of the above are being kept in a single assembly, and that I have declared the concrete classes as internal . This results in any "client" code being unable to access the concrete implementations, these are not visible externally to the logger framework assembly (at least they can't be accessed without some jiggery pokery Smile | <img src= " /> ) . As the ILogger interface is public, not internal, it is accessible from outside the dll (and therefore to the client) so I have set up the conditions for our problem: inaccessible concrete classes and, by extension, inaccessible constructors. How do we allow users of our logging framework to actually log?

Re-factoring towards the Factory Method Pattern    

The first iteration towards a neat solution is to abstract the creation of the concrete logger classes into types which the client is allowed to access. This is a very simple step, we add the following to our framework assembly:  

C#
public class SqlLoggerCreator
{
    public ILogger CreateLogger()
    {
        return new SqlLogger();
    }
}  

With a nearly identical class for the disk logger: 

C#
public class DiskLoggerCreator
{
    public ILogger CreateLogger()
    {
        return new DiskLogger();
    }
}  

At this point, we could rest as we have put a sticking-plaster over the problem, the client could call this code. But we are more savvy than to settle for that Wink | <img src= " /> . The user of the logging framework is not going to want to write code along the lines of:    

C#
public void Log(DiskLoggerCreator  creator)
{
    ILogger logger = creator.CreateLogger();
    Console.WriteLine(logger.Log());
}

public void Log(SqlLoggerCreator  creator)
{
    ILogger logger = creator.CreateLogger();
    Console.WriteLine(logger.Log());
}       

Not only is this duplicating work (bad), but if the additional concrete logger types are added, new methods like the above will need to be implemented by our user. As the methods being called are the same (I'll admit it - this was deliberate Smile | <img src= " /> ) we can make a further abstraction: we can make the creator classes implement  a common interface so they become in our second iteration:  

C#
public interface ILoggerCreator
{
    ILogger CreateLogger();
}

public class DiskLoggerCreator : ILoggerCreator
{
    public ILogger CreateLogger()
    {
        return new DiskLogger();
    }
}

public class SqlLoggerCreator : ILoggerCreator
{
    public ILogger CreateLogger()
    {
        return new SqlLogger();
    }
}   

Now the client code becomes a much more manageable from our user's point of view (as well as having other benefits I will list later):  

C#
public void Log(ILoggerCreator creator)
{
    ILogger logger = creator.CreateLogger();
    Console.WriteLine(logger.Log());
}    

 

This is now actually an implementation of the Factory Method Pattern (though we haven't broken it down yet it fulfils the intent described in the introduction) and we have also achieved our goals! 

If you examine the sample code, the main program calls each logger in turn, but does not itself access the concrete classes, so we have succeeded in isolating those. In the course of this, we have also necessarily developed a way to create concrete class instances via creator classes which are defined in a base interface.  In a sense we have created a "virtual constructor" - this is another name for this pattern. 

Getting to the Factory Method Pattern from our Code  

 First we should re-cap what we've done:  

  1. The concrete classes to be produced (SqlLogger and DiskLogger) have a base interface ILogger .
  2. As the concrete classes are inaccessible we have ultimately defined an interface for a creator which defines a method that returns an ILogger.    
  3. For each concrete type, we define a concrete creator type (SqlLoggerCreator and DiskLoggerCreator). These implement a common interface ILoggerCreator, which defines the method that does the work of returning the  ILogger 

Expressing this as UML (ignoring visibility on the concrete class side - it isn't that important now):  

Image 4  

We can strip out the  implementation specific stuff to produce one implementation of the  pattern 

Image 5   

This can be simplified even further to produce the diagram on the Wikipedia page (http://en.wikipedia.org/wiki/Factory_method_pattern) The biggest difference is really the "depends on" arrows linking the Creators with the classes these create . Additionally the UML diagram in the wikipedia entry only deals with one "product" type and  therefore one creator class. 

Note that we could replace all the Interfaces in this diagram with base classes or (a better option) abstract classes and it would still work.  I have  opted for interfaces as these provide the lowest coupling and complexity, they are also better for unit testing as I could mock my implementations, so I consider interfaces the best of the three inheritance options.  

Other Benefits    

Now we have the pattern constructed what else does it give us?   

  • We can put complicated set-up logic in the create methods. This is especially useful  when the set-up logic does not naturally sit inside either the class being constructed or the class using it.   
  • Commonly used code in set-up can also be placed in the  create methods - this removes duplication of code.     
  • We can now give the method constructing the class a more descriptive name - calling the constructor directly we are limited to type name.    
  • Following on from the design of the pattern - users of the produced interface can use types they are totally unaware of - they just need access to creators of these types. 
  • We are not limited to creating a new instance in the create methods - we could return a singleton instance for example.    

Points of Interest  

As described in the introduction, this is not the simplest implementation this also shows it is not the only implementation of this pattern, though it is a common one.  

There seems to be a lot of confusion about this pattern. One common (formally incorrect) implementation is to do something like the following:   

C#
public class Factory
{
     public IWhatever Create(int discriminator)
    {
        switch (discriminator)
        {
            case 1:
                return new Whatever1(); 
            break; 
            case 2: 
                return new Whatever2(); 
            break;    
        }  
    }  
}     

Where the italics are the interface/types used (in our example ILogger , DiskLogger and SqlLogger) and where discriminator  can be any type use to define which type is emitted. Although it is commonly called a Factory method (probably more sensibly than the one in this article!) it is not an implementation of the Factory Method Pattern 

As you use a Factory Method pattern in the real world, it quite often becomes inadequate over time. Commonly a different but closely related pattern the Abstract Factory Pattern is applied.  

History   

07/05/2013 - First Draft

08/05/2013 - Tidy up and clarification (hopefully) 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I Graduated in Natural Sciences (Chemistry & Physics) from Durham University, where I did not cover myself with glory, but did fill, and often cover, myself with beer.

I qualified as a secondary school teacher, but I hated teaching. I worked as an IT techhie for a few years but kept being promoted to IT Trainer, thanks to my teaching experience, which I also disliked. I spent some time working out what else I could do instead and reduced beer intake.

I realised that I should work as a programmer, having enjoyed it a hobby since I was a nipper in the halcyon days of the Sinclair Spectrum (48k, Rubber Keyboard). Spent two weeks working out why I didn't think of this to start with, instead of starting my dull-as-ditch-water Chemistry degree 8 years earlier. Had a beer to celebrate.

I Graduated in 2001 with an MSc from Newcastle Uni in Comp Sci. Did cover myself with glory, and drank some beer.

.Netting ever since, and loving it. Though I have largely given up beer due to not being able to hack the pace like I used to.

I was born, brought up, and have lived most of my life near Newcastle. In a fit of temporary insanity I moved to Amman, in my wife's homeland of Jordan, but made it back safely to the UK without any extra holes being made in my person by bullets. To be fair it was pretty safe at the time, if you ignored the roads.

Visit Jordan if you can by the way, the landscape is beautiful and varied, the food excellent and the people the friendliest on earth, after Geordies naturally Smile | :) .

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manfred Rudolf Bihy7-May-13 22:39
professionalManfred Rudolf Bihy7-May-13 22:39 
GeneralRe: My vote of 5 Pin
Keith Barrow7-May-13 22:47
professionalKeith Barrow7-May-13 22:47 
GeneralRe: My vote of 5 Pin
Manfred Rudolf Bihy7-May-13 22:50
professionalManfred Rudolf Bihy7-May-13 22:50 
GeneralRe: My vote of 5 Pin
Manfred Rudolf Bihy8-May-13 2:20
professionalManfred Rudolf Bihy8-May-13 2:20 
GeneralRe: My vote of 5 Pin
Keith Barrow8-May-13 2:22
professionalKeith Barrow8-May-13 2:22 
GeneralRe: My vote of 5 Pin
George Swan8-May-13 8:44
mveGeorge Swan8-May-13 8:44 
GeneralRe: My vote of 5 Pin
Manfred Rudolf Bihy8-May-13 12:21
professionalManfred Rudolf Bihy8-May-13 12:21 
But I didn't say were or was it where?

Thanks for correcting the corrector!


Cheers!

"I had the right to remain silent, but I didn't have the ability!"
Ron White, Comedian


GeneralRe: My vote of 5 Pin
Keith Barrow8-May-13 20:35
professionalKeith Barrow8-May-13 20:35 
QuestionMessage Closed Pin
7-May-13 20:49
Ricoleech7-May-13 20:49 
AnswerRe: Contruction Pin
Keith Barrow7-May-13 22:33
professionalKeith Barrow7-May-13 22:33 
GeneralRe: Contruction Pin
Manfred Rudolf Bihy7-May-13 22:44
professionalManfred Rudolf Bihy7-May-13 22:44 
GeneralRe: Contruction Pin
Keith Barrow7-May-13 22:45
professionalKeith Barrow7-May-13 22:45 
AnswerRe: Contruction Pin
Rage7-May-13 22:40
professionalRage7-May-13 22:40 
GeneralRe: Contruction Pin
Manfred Rudolf Bihy7-May-13 22:45
professionalManfred Rudolf Bihy7-May-13 22:45 
GeneralRe: Contruction Pin
Rage7-May-13 22:47
professionalRage7-May-13 22:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.