Factory Method Design Pattern CSharp


Factory Method Design Pattern

Factory

Def: An interface for creating an object,but let sub classes decide which class to instantiate. Factory Method lets a class defer instantiation to sub classes.

Factory methods prove useful when we are not sure what concrete implementation of of a class to instantiate. Instead, we can leave those details to the factory method.

Lets have a look on Dependency inversion principle’s solution  you can find it at end of my last post. There, ExportDataFromFile() method of DataExporter class creates instances of DbLogger, FileLogger and EventLogger concrete classes in catch blocks based on the exception which gets fired while executing the code in try block. That means the client class, DataExporter , knows well about the Concrete logger classes and can directly creates their instances  using “new” operator in the catch blocks.

To follow Factory method pattern, we need to move this instance creation headache to some other class (Factory class) with a method (Factory method)  which has logic to decide what type of logger (concrete) class’s instance should be created based on the exception type argument which will be passed to that method, like following.

public class DataExporter 
{
     public void ExportDataFromFile() 
     { 
           ExceptionLogger _exceptionLogger;
           try 
           { 
               //code to export data from files to database. 
           } 
           catch(Exception ex)
           { 
              // Get appropriate logger instance by calling  LoggoerFactory's GetLogger method.
              ILogger objILogger = LoggerFactory.GetLogger(ex); 

              _exceptionLogger = new ExceptionLogger(objILogger); 
              ExceptionLogger.LogException(ex);
           } 
    }
} 

public static class LoggerFactory 
{ 
     public ILogger GetLogger(Exception aException) 
     { 
          if(aException is IOException) 
          { 
             return DbLogger(); 
          } 
          else if(aException is SqlException) 
          { 
             return EventLogger(); 
          } 
          else 
          { 
             return FileLogger(); 
          } 
     } 
}

ExceptionLogger

Here we successfully reduced multiple catch blocks to one catch block by introducing new class LoggerFactory with a factory method GetLogger, which has logic to decide what kind on instance should be created and returned to the client based on the Exception argument type. Now our client class DataExporter need not to depend on concrete classed directly. Here LoggerFactory class takes care of the returning proper instance based on the exception. Following is the latest design based on the factory method pattern.

public interface ILogger 
{ 
     public void LogMessage(string aString); 
} 
public class DbLogger: ILogger 
{ 
     public void LogMessage(string aMessage) 
     { 
          //Code to write message in database. 
     } 
} 
public class FileLogger: ILogger 
{ 
     public void LogMessage(string aStackTrace) 
     { 
         //code to log stack trace into a file.
     } 
}
public class EventLogger: ILogger
{
      public void LogMessage(string aMessage)
      {
          //Code to write message in system's event viewer.
      }
}
public class DataExporter 
{ 
     public void ExportDataFromFile() 
     { 
         ExceptionLogger _exceptionLogger; 
         try 
         { 
             //code to export data from files to database. 
         } 
         catch(Exception ex) 
         { 
            //Get appropriate logger instance by calling 
            // LoggoerFactory's GetLogger method.
            ILogger objILogger = LoggerFactory.GetLogger(ex); 
            _exceptionLogger = new ExceptionLogger(objILogger); 
            _exceptionLogger.LogException(ex); 
         } 
     } 
} 
public static LoggerFactory 
{
    public ILogger GetLogger(Exception aException) 
    { 
         if(aException is IOException) 
         { 
             return DbLogger(); 
         } 
         else if(aException is SqlException) 
         { 
             return EventLogger(); } 
         else 
         { 
             return FileLogger(); 
         } 
    } 
} 
public class ExceptionLogger 
{ 
    private ILogger _logger; 
    public ExceptionLogger(ILogger aLogger) 
    { 
        this._logger = aLogger; 
    } 
    public void LogException(Exception aException) 
    { 
        string strMessage = GetUserReadableMessage(aException); 
        this._logger.LogMessage(strMessage); 
    } 
    private string GetUserReadableMessage(Exception aException) 
    { 
        string strMessage = string.Empty; 
        //code to convert Exception’s stack trace and message  to user readable format. 
        .... 
        .... 
        return strMessage; 
    } 
}

I hope this post gives you a clear idea on Factory method pattern.
Thanks,
Damu

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s