Blog Archives
Abstract Factory Pattern
There are many definitions on the internet of what the factory pattern would/should be. It is important to comply with your professor while you study at a university. Besides that programming is an art. It has nothing to do with naming conventions. Mona Lisa could be named Paul, you see. Only posh people care about technique naming. But if you paint a picture yourself, you don’t care about any technique naming convention at all; you only care about your results. And if people like it, then you are successful. It is the same with programming.
The Factory Method Pattern usually refers to a class that creates just one type of object.
The Abstract Factory Pattern usually refers to a class that can create various types of objects, which have something in common.
Besides that we have a lot of gibberish about some 10 and more years old pattern.
I could add a lot of code here, but it should suffice to just get the idea of it. Have a look at the above picture. An abstract class/interface is used as the base class for country specific factories. These factories create the objects.
The Z4 Model is built in Germany and China (just for demonstration purposes). Basically they are the same besides the difference between the Chinese and German regulations.
Now, translate that to your own business case. You may need a Factory that creates code for your Unix, Mac, and Windows system. On top of that you may have to create two distinct objects for your test and prod environment.
Factory pattern
Life was so easy. Why do we have to make it worse now and implement a so-called “Factory”?
Dependency Injection is about using abstract classes and interfaces to avoid concrete classes. Therefore the creation of a concrete class like “new Ferrari()” violates the idea of flexibility and dependency injection. The Factory Pattern allows us to instantiate concrete classes while depending only on abstract classes/interfaces. The development process becomes much easier in an environment where concrete classes are changing frequently.
using System; namespace demo { public abstract class Car { public string Name { get; protected set; } } public class Ferrari : Car { public Ferrari() { Name = "Red Speeder"; } } public class VW : Car { public VW() { Name = "German Classic"; } } public class Fiat : Car { public Fiat() { Name = "White Something"; } } public interface ICarFactory { Car GetObjectExpensive(); Car GetObjectCheap(); } // interface public class CarFactory : ICarFactory { public Car GetObjectExpensive() { return new Ferrari(); } public Car GetObjectCheap() { return new Fiat(); } } // class public class DependentClass { public readonly Car car = new Ferrari(); } // class public class IndependentClass { public readonly Car car; public IndependentClass(Car xCar) { car = xCar; } // constructor } // class class Program { static void Main(string[] args) { DependentClass d = new DependentClass(); CarFactory lCarFactory = new CarFactory(); IndependentClass i = new IndependentClass(lCarFactory.GetObjectExpensive()); Console.WriteLine(i.car.Name); // Red Speeder Console.ReadLine(); } // main } // class } // namespace
The code, which was dependent on the concrete class Ferrari, now only depends on the base class Car. You can easily inject any other car like VW or Fiat into your class. There is no need to search for all “new Ferrari()” commands in your code in case you need to change the type of car. It is all in one place. The dependency on the concrete class is gone.
We can increase the flexibility even further and use:
public interface ICarFactory { Car GetObject(string xType); } // interface public class CarFactory : ICarFactory { public Car GetObject(string xType) { switch (xType) { case "Expensive": return new Ferrari(); case "Average": return new VW(); case "Cheap": return new Fiat(); default: return null; } } } // class ... IndependentClass i = new IndependentClass(lCarFactory.GetObject("Expensive")); ...
The string can be replaced by an enum.
public enum eCar { Expensive, Average, Cheap }; public interface ICarFactory { Car GetObject(eCar xType); } // interface public class CarFactory : ICarFactory { public Car GetObject(eCar xType) { switch (xType) { case eCar.Expensive: return new Ferrari(); case eCar.Average: return new VW(); case eCar.Cheap: return new Fiat(); default: return null; } } // } // class public class IndependentClass1 { public readonly Car car; public IndependentClass1(Car xCar) { car = xCar; } // constructor } // class public class IndependentClass2 { public readonly Car car; public IndependentClass2() { CarFactory lCarFactory = new CarFactory(); car = lCarFactory.GetObject(eCar.Expensive); } // constructor } // class ... class Program { static void Main(string[] args) { DependentClass d = new DependentClass(); CarFactory lCarFactory = new CarFactory(); IndependentClass1 i1 = new IndependentClass1(lCarFactory.GetObject(eCar.Expensive)); IndependentClass2 i2 = new IndependentClass2(); Console.WriteLine(i2.car.Name); // Red Speeder Console.ReadLine(); } // main } // class
The Factory Pattern should only be used, when the need for it becomes great enough. Let’s say you are doing unit testing and you need to spoof the creator of an object. A Factory can be quite helpful then.
Factories add complexity to your code, so do not use them by default. They are conforming with Dependency Injection. Nevertheless, check the price you are willing to pay for independence.
Summary:
- A factory method returns one of several possible classes that share an interface/abstract class/(parent class).
- The class is chosen at runtime.
- Before: Car c = new Ferrari(); After: Car c = lCarFactory.GetObject(eCar.Expensive);
- Don’t use the Factory Pattern by default.