Abstract Factory
Overview
The Abstract Factory is a creational pattern, and is used when one would like to return one of several related objects.
UML Diagram
Structural Code
namespace DesignPatterns.AbstractFactory { using System; class Program { static void Main() { Client[] clients = { new Client(new Factory1()), new Client(new Factory2()) }; foreach (Client client in clients) { client.ExamineProductA(); client.ExamineProductB(); } Console.ReadLine(); } } interface ProductA { void Examine(); } interface ProductB { void Examine(); } class ProductA1 : ProductA { public void Examine() => Console.WriteLine(nameof(ProductA1)); } class ProductA2 : ProductA { public void Examine() => Console.WriteLine(nameof(ProductA2)); } class ProductB1 : ProductB { public void Examine() => Console.WriteLine(nameof(ProductB1)); } class ProductB2 : ProductB { public void Examine() => Console.WriteLine(nameof(ProductB2)); } interface Factory { ProductA CreateProductA(); ProductB CreateProductB(); } class Factory1 : Factory { public ProductA CreateProductA() => new ProductA1(); public ProductB CreateProductB() => new ProductB1(); } class Factory2 : Factory { public ProductA CreateProductA() => new ProductA2(); public ProductB CreateProductB() => new ProductB2(); } class Client { ProductA _productA; ProductB _productB; public Client(Factory factory) { _productA = factory.CreateProductA(); _productB = factory.CreateProductB(); } public void ExamineProductA() => _productA.Examine(); public void ExamineProductB() => _productB.Examine(); } }
Structural Code Out
ProductA1 ProductB1 ProductA2 ProductB2
Structural Code Discussion
As can be seen here, we can change the factory to get a different set of related objects. If we need a new set of related objects, we can create a couple of new objects inheriting from our abstract product interfaces, and an accompanying factory inheriting from the abstract interface Factory, and our Client stays completely agnostic.
Pattern Example
namespace DesignPatterns.AbstractPattern { using System; class Program { static void Main() { Client[] customers = { new Client(new HondaFactory()), new Client(new ToyotaFactory()) }; foreach(Client customer in customers) { customer.ExamineLuxuryCar(); customer.ExamineAffordableCar(); } Console.ReadLine(); } } interface ICar { void ExamineAffordableCar(); } interface ILuxuryCar { void ExamineLuxuryCar(); } interface IFactory { ICar GetCar(); ILuxuryCar GetLuxuryCar(); } class HondaCar : ICar { public void ExamineAffordableCar() => Console.WriteLine("A spacious Honda Accord."); } class HondaLuxuryCar : ILuxuryCar { public void ExamineLuxuryCar() => Console.WriteLine("A luxurious Acura Legend."); } class HondaFactory : IFactory { public ICar GetCar() => new HondaCar(); public ILuxuryCar GetLuxuryCar() => new HondaLuxuryCar(); } class ToyotaCar : ICar { public void ExamineAffordableCar() => Console.WriteLine("A reliable Toyota Camry."); } class ToyotaLuxuryCar : ILuxuryCar { public void ExamineLuxuryCar() => Console.WriteLine("A bold Lexus ES Hybrid."); } class ToyotaFactory : IFactory { public ICar GetCar() => new ToyotaCar(); public ILuxuryCar GetLuxuryCar() => new ToyotaLuxuryCar(); } class Client { ICar _car; ILuxuryCar _luxuryCar; public Client(IFactory factory) { _car = factory.GetCar(); _luxuryCar = factory.GetLuxuryCar(); } public void ExamineAffordableCar() => _car.ExamineAffordableCar(); public void ExamineLuxuryCar() => _luxuryCar.ExamineLuxuryCar(); } }
Example Code Out
A luxurious Acura Legend. A spacious Honda Accord. A bold Lexus ES Hybrid. A reliable Toyota Camry.