You can read my previous posts about design patterns here:
An abstract factory provides an interface for creating families of related objects without specifying their concrete classes.
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. Object creation has been abstracted and there is no need for hard-coded class names in the client code.
For an example, take a real-world demonstrates the Factory method offering flexibility in creating different documents. The derived Document classes Report and Resume instantiate extended versions of the Document class. Here, the Factory Method is called in the constructor of the Document base class.
using System;
using System.Collections.Generic;
using System.Text;
namespace DesignPatternConsole
{
/// <summary>
/// The 'Product' abstract class
/// </summary>
abstract class Page
{
}
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class SkillsPage : Page
{
}
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class EducationPage : Page
{
}
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class ExperiencePage : Page
{
}
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class IntroductionPage : Page
{
}
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class ResultsPage : Page
{
}
/// <summary>
/// The 'Creator' abstract class
/// </summary>
abstract class Document
{
private List<Page> _pages = new List<Page>();
// Constructor calls abstract Factory method
public Document()
{
this.CreatePages();
}
public List<Page> Pages
{
get { return _pages; }
}
// Factory Method
public abstract void CreatePages();
}
/// <summary>
/// A 'ConcreteCreator' class
/// </summary>
class Resume : Document
{
// Factory Method implementation
public override void CreatePages()
{
Pages.Add(new SkillsPage());
Pages.Add(new EducationPage());
Pages.Add(new ExperiencePage());
}
}
/// <summary>
/// A 'ConcreteCreator' class
/// </summary>
class Report : Document
{
// Factory Method implementation
public override void CreatePages()
{
Pages.Add(new IntroductionPage());
Pages.Add(new ResultsPage());
}
}
class AbstractFactory
{
/// <summary>
/// Entry point into console application.
/// </summary>
static void Main()
{
// Note: constructors call Factory Method
Document[] documents = new Document[2];
documents[0] = new Resume();
documents[1] = new Report();
// Display document pages
foreach (Document document in documents)
{
Console.WriteLine("\n" + document.GetType().Name + "--");
foreach (Page page in document.Pages)
{
Console.WriteLine(" " + page.GetType().Name);
}
}
// Wait for user
Console.ReadKey();
}
}
}
Output :
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.
Happy Coding!!!