Click here to Skip to main content
15,885,208 members
Articles / Programming Languages / C#
Article

Factory Design pattern

Rate me:
Please Sign up or sign in to vote.
3.39/5 (15 votes)
6 May 2006CPOL3 min read 61.4K   826   29   4
This article describes the commonly used design pattern: The Factory Design Pattern.

Introduction

While designing software, we generally think of high-level abstraction. By doing so, we can reduce the complexity by reducing the dependency. One such abstraction is the software design patterns. They have been successfully applied in the past to simplify and solve recurring problems in software development. Most of the instances of the design patterns are found in the .NET class library. This article describes the commonly used design pattern: The Factory Design Pattern.

Background

The Factory Design pattern is used when a class cannot anticipate the type of object it must create or when you want to delegate the responsibility of creations of object to another class so that you need not worry about the complexity involved in creation of the object. This reduces the code redundancy in the application.

The intent of The Factory Design Pattern (or the Factory Method (Gof)) is to define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory Method allows a class to defer instantiation to the subclasses. (Reference).

Implementation

To explain this, I have used the example of a logger. Every application uses logging to log messages for debugging, analyzing or auditing. There can be various types of logging like logging to text file, logging to event logger or to SQL server, etc. The application should not have the knowledge of which logger it is using and hence it should be abstracted from the creation of the logger component. For this to happen, the responsibility of creating the logger component is given to a special class know as the LoggerFactory. This class knows how to create different kind of loggers, what are the parameters to be set for each type of logger, etc. Now the application need not know about the logger creation, it will ask the Factory to create a corresponding logger (which is configured) and start using it.

Design

Design screenshot

I have defined an interface for Logging by Name Ilogger. TxtFileLogger, EventLogger and DummyLogger are the various types of loggers which implement the Ilogger. LoggerFactory is the Factory class and knows how to create the specified logger. The application (MainAPP) uses the Config class to load the configurations set for the application. Depending on the type of logger configured, the application asks the factory to create the logging component. The Factory creates the corresponding logger, initializes the component with specific configurations (obtained by Config) and then returns it. The application can now use it for logging without having to know about the component.

Following is the implementation of the Factory class:

C#
using System;
using SampleFactory.Configuration;
using System.Collections.Specialized;
namespace SampleFactory.Logging
{
    /// <summary>
    /// This class exhibits the Factory Design Pattern.
    /// This class knows how to create a corresponding logger component.
    /// The clients requiring the logger component need to ask this factory
    /// for the component by specifying their ID and hence need not worry about
    /// how to create the component themselves.
    /// </summary>
    public class LoggerFactory
    {
        /// <summary>
        /// Private constructors, since no objects of LoggerFactory required
        /// </summary>
        private LoggerFactory()
        {
        } 
        static public ILogger CreateLogger(string identifier) 
        {
            ILogger logger = null;
            if(identifier.CompareTo("TxtFileLogger") == 0) {
                Console.WriteLine("Loading {0} logger", identifier);
                Console.WriteLine("All messages will be logged to text file");
                // Get the configuration related to TxtFileLogger and
                // create the component.
                NameValueCollection txtConfig = Config.TxtFileLoggerConfig;
                logger = new TxtFileLogger(txtConfig["FileName"]);
            }
            else if(identifier.CompareTo("EventLogger") == 0) {
                Console.WriteLine("Loading {0} logger", identifier);
                Console.WriteLine("All messages will be logged to EventLog");
                // Get the configuration related to EventLogger and
                // create the component.
                NameValueCollection eventConfig = Config.EventLoggerConfig;
                logger = new EventLogger(eventConfig["LogName"], 
			eventConfig["MachineName"]);
           }
           else {
                Console.WriteLine("Invalid Logger ({0}) 
			configured: using DummyLogger", identifier);
                // Invalid configuration, create a dummy logger which will do nothing
                // and return it (used for disabling logging)
                logger = new DummyLogger();
           }
           return (logger);
        }
    }
}

Following are the contents of the configuration file:

XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="TxtFileLoggerConfigurations" 
	type="System.Configuration.NameValueSectionHandler"/>
<section name="EventLoggerConfigurations" 
	type="System.Configuration.NameValueSectionHandler"/>
</configSections>
<appSettings>
<add key="LogClassID" value="TxtFileLogger" />
</appSettings>
<TxtFileLoggerConfigurations> 
<add key="FileName" value="TxtFileLogger.txt"/>
</TxtFileLoggerConfigurations>
<EventLoggerConfigurations> 
<add key="LogName" value="EventLogger"/>
<add key="MachineName" value="."/>
</EventLoggerConfigurations>
</configuration>

Using the Sample

Run the sample and you will get a console application with TxtFileLogger set as default logger. Enter some message, type ‘END’ to stop. Check that TxtFileLogger.txt will be created in the current folder which will contain the messages you have typed. Now close the application and change the logger by changing the configuration in SampleFactory.exe.config, now see how it works. You can disable the logging by configuring the logger a DummyLogger. This way the application using the logger to log is not aware of which component it is using.
Hope this explains the use of the factory design pattern.

History

  • 6th May, 2006: Initial post

License

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


Written By
Web Developer
India India
I have been working in software industry for the past 5 years now. Enjoy working on complex and new technologies. Worked on Microsoft technologies Like VC++, COM, XML, SQL. Currently working on .Net, C#.

Comments and Discussions

 
SuggestionI prefer classic example Pin
JohnDetroit6-Apr-13 4:14
JohnDetroit6-Apr-13 4:14 
GeneralThis example has one limitation Pin
dharmesh.parekh19-Dec-06 19:43
dharmesh.parekh19-Dec-06 19:43 
GeneralRe: This example has one limitation Pin
Madhu Raykar1-Jan-07 23:45
Madhu Raykar1-Jan-07 23:45 
GeneralThis is a static factory class Pin
tim73di6-May-06 3:57
tim73di6-May-06 3:57 
In the GoF book, factory design patterns include the Factory method pattern and the Abstract Factory pattern. According to Robert C. Martin, the Abstract Factory pattern is probably a little bit more commonly used.

It seems to me that a simple static factory class is presented in this article. Although it is very widely used, the simple static factory isn't actually a (traditional) design pattern; it is more of a programming idiom (p.117 of <<head-first design="" patterns="">>). This approach can also be found in Martin Fowler's book <<refactoring: improving="" the="" design="" of="" existing="" code="">>, and Joshua Kerievsky's book <<refactoring to="" patterns="">>.

But, thank you very much any way. From time to time I myself use it anyways.


Best regards.

tim

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.