The factory method pattern is a design pattern that allows for the creation of objects without specifying the type of object that is to be created in code. A factory class contains a method that allows determination of the created type at run-time.
This is a third of Gang of Four patterns. It also belongs to the creational patterns group. This pattern is also known as Virtual Constructor pattern. The factory method pattern defines an interface for creating an object and leaves the choice of type to the subclasses. Factory method design pattern makes a design more customizable and only a little complicated. Other design pattern require new classes, whereas factory method only requires a new operation.
The UML diagram below describes an implementation of the factory method design pattern. This diagram consists of four classes:
- FactoryBase: this is an abstract class for the concrete factory classes which will return new objects. In some cases it could be a simple interface containing the signature for the factory method. This class contains
FactoryMethod
which returns a ProductBase
object.
- ConcreteFactory: represents concrete implementation of factory. Usually this class overrides the generating
FactoryMethod
and returns a ConcreteProduct
object.
- ProductBase: this is a base class for all products created by concrete factories. In some cases it could be a simple interface.
- ConcreteProduct: this is a concrete implementation of
ProducBase
. Concrete product classes can include specific functionality. This objects are created by factory methods.
Hide Shrink Copy Code
static class Program
{
static void Main()
{
FactoryBase factory = new ConcreteFactory();
ProductBase product = factory.FactoryMethod(1);
product.ShowInfo();
product = factory.FactoryMethod(2);
product.ShowInfo();
}
}
public abstract class FactoryBase
{
public abstract ProductBase FactoryMethod(int type);
}
public class ConcreteFactory : FactoryBase
{
public override ProductBase FactoryMethod(int type)
{
switch (type)
{
case 1:
return new ConcreteProduct1();
case 2:
return new ConcreteProduct2();
default:
throw new ArgumentException("Invalid type.", "type");
}
}
}
public abstract class ProductBase
{
public abstract void ShowInfo();
}
public class ConcreteProduct1 : ProductBase {
public override void ShowInfo()
{
Console.WriteLine("Product1");
}
}
public class ConcreteProduct2 : ProductBase {
public override void ShowInfo()
{
Console.WriteLine("Product2");
}
}
In this example I have chosen the vehicle manufacturing example again. We have one interface IVehicleFactory
with one method CreateVehicle
which returns Vehicle
object. Another two classes FordExplorerFactory
and LincolnAviatorFactory
are concrete implement this interface. In case of FordExplorerFactory
, method CreateVehicle
returns FordExplorer
object which derives from abstract Vehicle
class and overrides ShowInfo
method. This method only displays information about vehicle. FordExploredClass
has one default constructor which fills properties of this object.
In case of LincolnAviatorFactory
is a situation a slightly bit different. Method CreateVehicle
returns LincolnAviator
object, but this object has one constructor with parameters which values are used to fill object’s properties.
This example demonstrates how to use different factories for creating a different types of objects.
Hide Shrink Copy Code
class Program
{
static void Main(string[] args)
{
IVehicleFactory factory = GetFactory("FactoryMethodPattern.ConcreteFactories.LincolnAviatorFactory");
var lincolnAviator = factory.CreateVehicle();
lincolnAviator.ShowInfo();
factory = GetFactory("FactoryMethodPattern.ConcreteFactories.FordExplorerFactory");
var fordExplorer = factory.CreateVehicle();
fordExplorer.ShowInfo();
}
static IVehicleFactory GetFactory(string factoryName)
{
return Assembly.GetExecutingAssembly().CreateInstance(factoryName) as IVehicleFactory;
}
}
public interface IVehicleFactory
{
Vehicle CreateVehicle();
}
public abstract class Vehicle
{
public string Model { get; set; }
public string Engine { get; set; }
public string Transmission { get; set; }
public string Body { get; set; }
public int Doors { get; set; }
public List<string> Accessories = new List<string>();
public abstract void ShowInfo();
}
public class FordExplorerFactory:IVehicleFactory
{
public Vehicle CreateVehicle()
{
return new FordExplorer();
}
}
public class LincolnAviatorFactory:IVehicleFactory
{
public Vehicle CreateVehicle()
{
return new LincolnAviator("Lincoln Aviator",
"4.6 L DOHC Modular V8",
"5-speed automatic",
"SUV",4);
}
}
public class FordExplorer:Vehicle
{
public FordExplorer()
{
Model = "Ford Explorer";
Engine = "4.0 L Cologne V6";
Transmission = "5-speed M50D-R1 manual";
Body = "SUV";
Doors = 5;
Accessories.Add("Car Cover");
Accessories.Add("Sun Shade");
}
public override void ShowInfo()
{
Console.WriteLine("Model: {0}", Model);
Console.WriteLine("Engine: {0}", Engine);
Console.WriteLine("Body: {0}", Body);
Console.WriteLine("Doors: {0}", Doors);
Console.WriteLine("Transmission: {0}", Transmission);
Console.WriteLine("Accessories:");
foreach (var accessory in Accessories)
{
Console.WriteLine("\t{0}", accessory);
}
}
}
public class LincolnAviator:Vehicle
{
public LincolnAviator(string model, string engine, string transmission, string body, int doors)
{
Model = model;
Engine = engine;
Transmission = transmission;
Body = body;
Doors = doors;
Accessories.Add("Leather Look Seat Covers");
Accessories.Add("Chequered Plate Racing Floor");
Accessories.Add("4x 200 Watt Coaxial Speekers");
Accessories.Add("500 Watt Bass Subwoofer");
}
public override void ShowInfo()
{
Console.WriteLine("Model: {0}", Model);
Console.WriteLine("Engine: {0}", Engine);
Console.WriteLine("Body: {0}", Body);
Console.WriteLine("Doors: {0}", Doors);
Console.WriteLine("Transmission: {0}", Transmission);
Console.WriteLine("Accessories:");
foreach (var accessory in Accessories)
{
Console.WriteLine("\t{0}", accessory);
}
}
}