Pranay Rana: Factory Design Pattern With Generics

Tuesday, May 22, 2018

Factory Design Pattern With Generics

Factory Method design pattern is one of the highly used design pattern, which is used in project to centralize creation of similar family object in application. It's part of creation design patterns as it helps to create objects in application.



Why to Centralize Object creation with Facotry?

  1. To avoid object creation every where in application with New. 
  2. To create object at run-time which serves purpose, based on requirement (i.e. based on input parameters). 
Factory Pattern Implementation

Below is class diagram and code implementation of Factory pattern.

Below code, centralize creation of command objects with help of Factory design pattern. Code below works as below

  • Code below creates different command to perform task such as addemployee, editemployee etc.
  • It's scalable as if developer wants to add new command let's say deleteemployee then it require to create new DeleteEmployee command which inherits from ICommand as other commands do.
  • CommandFactory , its factory pattern base class which has method GetCommand to return requested command based on input string argument. Modification required in GetCommand method when new command need to be added in application.
  • Program is client class which make use of CommandFactory and execute returned command.

    class Program
    {
        static void Main(string[] args)
        {
            ICommand cmd = CommandFactory.GetCommand("AddEmployee");
            Console.WriteLine(cmd.GetType());
            Console.ReadLine();
        }
    }

    public class CommandFactory
    {
        public static ICommand GetCommand(string cmdName)
        {
            if(cmdName=="AddEmployee") 
            {
                return new AddEmployee();
            } 
     else if(cmdName=="EditEmployee") 
            {
                return new EdutEmployee();
            }

            return new NullCommand();
        }
    }

    public class NullCommand : ICommand
    {
        public bool CanExecute()
        {
             Console.WriteLine("Null command");
    return true;
        }

        public void Execute()
        {
           Console.WriteLine("Null command");
        }
    }

    public class AddEmployee : ICommand
    {
        public bool CanExecute()
        {
            //validation
   return true;
        }

        public void Execute()
        {
          //code to execute
        }
    }
 
    public class EditEmployee : ICommand
    {
        public bool CanExecute()
        {
            //validation
             return true;
        }

        public void Execute()
        {
          //code to execute
        }
    }

    public interface ICommand
    {
        bool CanExecute();
        void Execute();
    } 

Following are issues with above code
  1. One big issue with above code is , it's violate Open Close principle. Because whenever new command added in application, developer need to go to Command Factory and need to add if condition for creating it.
    For Example: when there is need of adding Delete command , developer need to open CommandFactory class and need to add if clause for that.
  2. CommandFactory, GetCommand takes string argument to create and return instance of command. If developer pass wrong string argument value it will end up with NullCommand object (which is based on Null object pattern).
    So its not type safe implementation.
  3. CommandFactory, GetCommand can only return ICommand. If developer added new property/method let's say xyz which is specific to command ex. AddEmployee, then developer cannot access it like addCommandObj.xyz as return Command is of type ICommand and it doesnt has that property. 
Generics Based Factory Pattern Implementation

Solution to problem listed above is make use of factory pattern using Generics. Below is diagram and code of implementation


    class Program
    {
        static void Main(string[] args)
        {
            ICommand cmd = CommandFactory.GetCommand<AddEmployee>();
            Console.WriteLine(cmd.GetType());
            AddEmployee addEmployeeCmd = CommandFactory.GetCommand<AddEmployee>();
            Console.WriteLine(addEmployeeCmd.NewEmployeeId);
            Console.ReadLine();
        }
    }

    public class CommandFactory
    {       
        //only create object of type which implement ICommand
        public static T GetCommand<T>() where T:  ICommand
        {
          //it create object using Template type T and by making use of reflection
          //once create factory this way there is no need to open it again for modification
            Type type = typeof(T);
            Object obj = Activator.CreateInstance(type);
            return (T)obj;
        }
    }

    public class EditCommand : ICommand
    {
        public bool CanExecute()
        {
            //validation
            return true;
        }

        public void Execute()
        {
            //code to execute 
        }
    }

    public class AddEmployee : ICommand
    {
        private int newEmployeeId;
        public int NewEmployeeId
        {
            get { return newEmployeeId; }
        }

        public bool CanExecute()
        {
            return true;
        }

        public void Execute()
        {
            //execute code to create employee
            this.newEmployeeId = 1;//created employeeid 
        }
    }

    public interface ICommand
    {
        bool CanExecute();
        void Execute();
    } 

Following are advantages (solutions for previous approach problem) of generics based implementation

  1. It doesn't violate open close principle as object get created using reflection and using Generics Template type T in CommandFacoty class - GetCommand method. Check CommandFacotry Class in above code.
  2. By making use of Generics, it makes CommandFactory strongly type and there is no need string as argument based on which GetCommand method creating object in previous implementation.
     public static T GetCommand<T>() where T:  ICommand 
    if you see signature of GetCommand now,  it force Template type T must implement ICommand interface and so that it only going to create object of types which implement ICommand.
  3. Now factory can return object of specific implemented type like AddEmployee
      AddEmployee addEmployeeCmd = CommandFactory.GetCommand<AddEmployee>();
    
    Above line of code in Program class Main method proves point that now factory can return implemented type that can also be convert to to parent type ICommand.
Wrapping up
Factory pattern is one of the highly used deign pattern which used in most of the application to create and centralize object creation. So when it written not strongly type based way can lead to problem. So it's better to implement it strongly type based way (Generics implementation) to avoid issues and it helps to stick your code with SOLID principle.


No comments:

Post a Comment