Abstract Factory Pattern
Abstract Factory Pattern
Today I'm going to write about one of the most popular patterns in the design
patterns world - the abstract factory.
You can read my previous posts about design patterns here:
Structural patterns
Decorator pattern
Proxy pattern
Facade pattern
Adapter pattern
Composite pattern
Bridge pattern
Flyweight pattern
Creational patterns
Singleton pattern
What is Abstract Factory Pattern
The abstract factory provides an interface for creating families of related
objects without concrete classes specifications.
The abstract factory dictates which products the concrete factories will produce.
Each concrete factory can build different products of different types.
The only way to get the products by the client is through the factory which isolate
the products definition and creation.
The benefits of using the pattern are the isolation of concrete classes, it makes it easy to
exchange product families and it makes the products consistent.
The drawback of the pattern is that the support of new products is difficult.
For a UML diagram of the pattern go to dofactory site.
C# Example
Lets look at an example of abstract factory use:
#region Helper Enum
enum eMaterialType
{
Wood,
Iron
}
#endregion
#region Abstarct Factory
interface IFactory
{
#region Methods
Table CreateTable();
Door CreateDoor();
#endregion
}
#endregion
#region Concrete Factories
/// Concrete factory for wood products
class WoodFactory : IFactory
{
#region IFactory Members
public Table CreateTable()
{
return new WoodTable();
}
public Door CreateDoor()
{
return new WoodDoor();
}
#endregion
}
// Concrete factory for iron products
class IronFactory : IFactory
{
#region IFactory Members
public Table CreateTable()
{
return new IronTable();
}
public Door CreateDoor()
{
return new IronDoor();
}
#endregion
}
#endregion
#region Abstarct Products
// The two products in the example
// share the same material property
interface IProduct
{
string Material { get; }
}
// Product A
abstract class Table : IProduct
{
#region IProduct Members
public string Material
{
get
{
return eMaterialType.Wood.ToString();
}
}
#endregion
}
// Product B
abstract class Door : IProduct
{
#region IProduct Members
public string Material
{
get
{
return eMaterialType.Iron.ToString();
}
}
#endregion
}
#endregion
#region Concrete Products
#region Wood Products
class WoodTable : Table
{
// implement whatever you need
}
class WoodDoor : Door
{
// implement whatever you need
}
#endregion
#region Iron Products
class IronTable : Table
{
// implement whatever you need
}
class IronDoor : Door
{
// implement whatever you need
}
#endregion
#endregion
The example is easy to understand.
I first created the IProduct interface because the products share the same property
(Material). Then, I created the abstract products of Door and Table.
For every material I created a relevant product (IronDoor, IronTable, WoodDoor and
WoodTable). After I created the products it was the time to create the factories.
I first create an interface (IFactory) which is the abstract factory.
The interface dictate that every concrete factory need to create doors and tables.
Next, I created the concrete factories which are the WoodFactory and the IronFactory.
Those factories will create the relevant product for every create method.
Summary
To sum up the post, use the pattern whenever you need that the application you build
should be independent of how the products are created or composed. Use it also when you
have families of related objects.
One thing you need to keep in mind. It's not easy to add new products to the factory.
Adding a new product to the factory requires changes in the concrete factories interface.
The client also need to change in order to use the new product.
The next pattern in the series will be the prototype pattern.