Wednesday, October 10, 2012

Factory Pattern

*Disclaimer these writings are for my own learning purposes not as advice to others. If any part is incorrect please feel free to constructively discuss.  

Previously I discussed the Strategy Pattern Today I've spent some time looking at the Factory Pattern.
What I've learned is that opposed to the Strategy pattern which is a behavioral pattern the Factory pattern is a creational pattern. So what does that mean? Many times a creational pattern may be used in a framework. But almost always the reason is to help deal with complexities involved in object creation. If there are some choices to be made about what type of object to instantiate, if the object can be represented in a general form then the creational pattern may work well for that situation. From my reading the key principle in the creational pattern is encapsulation. when designing using this pattern you're going to encapsulate knowledge of what concrete class the framework uses, and how they are created.

But I don't just want to regurgitate my readings. Here is the example I put together to help myself understand the pattern better:

(Another car example).

*Note you can use an abstract base class or an interface. I chose an interface this time just because I used an abstract base last time.

//Here is the interface. Simple enough. (Drivetrain being the distinguisher).
 public interface Car
 {
        String Title { get; }
        DriveTrain DriveTrain { get; }
 }

//A couple of concrete types implementing the interface
class ClassicCar : Car
{
      public DriveTrain DriveTrain
      {
          get { return CarFactoryPattern.DriveTrain.TwoByFor; }
      }

      public string Title
      {
          get { return "a great classic"; }
      }
}

class SportsCar : Car
{
      public DriveTrain DriveTrain
      {
          get { return CarFactoryPattern.DriveTrain.AllWheelDrive; }
      }

      public string Title
      {
          get { return "an awesome sports car"; }
      }
}

class SUV : Car
{
      public DriveTrain DriveTrain
      {
          get { return CarFactoryPattern.DriveTrain.FourByFour; }
      }

      public string Title
      {
          get { return "an all purpose utility vehicle"; }
      }
 }

//The factory
public static class Factory
{
      public static Car GetCar(DriveTrain driveTrain)
      {
          switch (driveTrain)
          {
              case DriveTrain.AllWheelDrive:
                  return new SportsCar();
              case DriveTrain.FourByFour:
                  return new SUV();
              case DriveTrain.TwoByFor:
                  return new ClassicCar();
              default:
                  return null;
          }
      }
}

//The client
static void Main(string[] args)
{
          Console.WriteLine("Pick a drivetrain to go in your new car: 1 AWD, 2 4X4, 3 2WD.");
          switch (Console.ReadLine())
          {
              case "1":
                  Console.WriteLine("You will be driving " + Factory.GetCar(DriveTrain.AllWheelDrive).Title);
                  break;
              case "2":
                  Console.WriteLine("You will be driving " + Factory.GetCar(DriveTrain.FourByFour).Title);
                  break;
              case "3":
                  Console.WriteLine("You will be driving " + Factory.GetCar(DriveTrain.TwoByFor).Title);
                  break;
              default:
                  Console.WriteLine("Please make a valid selection.");
                  break;
          }
}

The point is creation of the type is encapsulated. How the types tie together or how they are differentiated is encapsulated. The client just knows it needs a car and that it needs to be of a certain drivetrain type.

The source code can be found here. (VS 2012) Example solution

No comments:

Post a Comment