Abstract Factory Design Pattern in .NET — Real-Time Finance Example

The Abstract Factory pattern is used to create families of related or dependent objects without specifying their concrete classes. It’s especially useful when objects must be created together and must be compatible with one another.

 

Purpose

To encapsulate the creation of related objects and ensure the client uses compatible types from the same family. This helps maintain consistency and allows easy replacement of entire families.

 

Key Characteristics

  • Defines a factory interface for a group of related products
  • Each concrete factory creates a specific variant of each product
  • Ensures that the created products work together properly

 

Pros

  • Promotes consistency among related objects
  • Supports the Open/Closed Principle
  • Keeps client code independent of concrete implementations

 

Cons

  • Can result in complex class hierarchies
  • Extending families can be harder without modifying interfaces

 

Use Cases

  • UI themes: Create consistent buttons, dropdowns, inputs for dark/light themes
  • Payment Gateways: Different services (auth, refund, settlement) for Razorpay, Stripe, etc.
  • Report Generators: Create consistent headers/bodies for PDF, Excel, CSV formats

 

Real-Time Finance Example: Financial Report Generation

A banking system needs to generate reports in multiple formats (PDF, Excel). Each format must have a header and body that are visually and structurally compatible. The Abstract Factory pattern ensures that the correct parts are created as a set.

 

1. Define Abstract Product Interfaces

public interface IReportHeader

{

    void PrintHeader();

}

 

public interface IReportBody

{

    void PrintBody();

}

 

2. Implement Concrete Products

// PDF products

public class PDFHeader : IReportHeader

{

    public void PrintHeader()

    {

        Console.WriteLine("PDF Header: Financial Report");

    }

}

 

public class PDFBody : IReportBody

{

    public void PrintBody()

    {

        Console.WriteLine("PDF Body: Revenue, Expenses, Profit...");

    }

}

 

// Excel products

public class ExcelHeader : IReportHeader

{

    public void PrintHeader()

    {

        Console.WriteLine("Excel Header: Financial Report");

    }

}

 

public class ExcelBody : IReportBody

{

    public void PrintBody()

    {

        Console.WriteLine("Excel Body: Revenue, Expenses, Profit...");

    }

}

 

3. Define the Abstract Factory

public interface IReportFactory

{

    IReportHeader CreateHeader();

    IReportBody CreateBody();

}

 

4. Implement Concrete Factories

public class PDFReportFactory : IReportFactory

{

    public IReportHeader CreateHeader() => new PDFHeader();

    public IReportBody CreateBody() => new PDFBody();

}

 

public class ExcelReportFactory : IReportFactory

{

    public IReportHeader CreateHeader() => new ExcelHeader();

    public IReportBody CreateBody() => new ExcelBody();

}

 

5. Client Code (Uses Only Abstractions)

public class ReportGenerator

{

    private readonly IReportHeader _header;

    private readonly IReportBody _body;

 

    public ReportGenerator(IReportFactory factory)

    {

        _header = factory.CreateHeader();

        _body = factory.CreateBody();

    }

 

    public void GenerateReport()

    {

        _header.PrintHeader();

        _body.PrintBody();

    }

}

 

6. Usage Example

class Program

{

    static void Main()

    {

        Console.WriteLine("Generating PDF Report:");

        var pdfReport = new ReportGenerator(new PDFReportFactory());

        pdfReport.GenerateReport();

 

        Console.WriteLine();

 

        Console.WriteLine("Generating Excel Report:");

        var excelReport = new ReportGenerator(new ExcelReportFactory());

        excelReport.GenerateReport();

    }

}

 

Output

Generating PDF Report:

PDF Header: Financial Report

PDF Body: Revenue, Expenses, Profit...

 

Generating Excel Report:

Excel Header: Financial Report

Excel Body: Revenue, Expenses, Profit...

 

Benefits of This Design

  • Ensures components created together are compatible and consistent
  • Allows easy addition of new families (e.g., CSVReportFactory)
  • Keeps the client focused on what to generate, not how to generate it


Comments

Popular posts from this blog

Multiline to singleline IN C# - CODING

EF Core interview questions for beginners

EF Core interview questions for experienced