jeudi 18 novembre 2021

Using fluent builder pattern for generating pdf

I'm testing to use a fluent builder pattern for generating a pdf file using AbcPDF. I've looked at several methods of accomplishing this and I'd be very glad to get some input on what I've written so far to see if I'm going in the right direction or if there's some criticism.

The idea is that I have a builder for each component in the pdf:

  • Footer builder
  • Page numbers builder
  • Index builder
  • Project information builder
  • Customer information builder
  • Document content (the main text) builder

So for example I have an "umbrella" builder for generating a customer document that can contain some or all parts in that list. And then another "umbrella" builder for generating another type of document but contains some parts of the list.

The main idea is to use the builders in the list for generating different types of documents. For example a sales report may contain some main content, footer and page numbers, whilst a customer document also needs customer information and maybe project information.

I've looked at some that use inheritance with recursive generics, and fatected builders but in those examples my "component builders" (ref list above) would be coupled to the sales report builder or customer document builder. At least in those examples I've read(?).

But yeah, the general idea is to have small builders not coupled with anything that can be reused by bigger builders that expose a set of the small builders that are appropriate to have in that context. Or is there a pattern better suited for this goal? Thanks :) And yeah, I don't know if the interfaces are neccessary, but I guess I kept them there to hear about what you guys thought about it.

    public class CustomerDocumentBuilder
{
    private readonly Doc _document;

    private CustomerDocumentBuilder()
    {
        _document = new();
    }

    public static CustomerDocumentBuilder Create() => new();

    public void Build()
    {
        _document.Save("C:\\pdf\\textflow.pdf");
    }

    public CustomerDocumentBuilder AddDocument(
        DocumentInformation documentInfo)
    {
        new DocumentBuilder(_document).AddDocument(documentInfo);
        return this;
    }

    public CustomerDocumentBuilder AddCustomerInformation(
        CustomerInformation customerInfo)
    {
        new CustomerBuilder(_document).AddCustomerInformation(customerInfo);
        return this;
    }

    public CustomerDocumentBuilder AddProjectInformation(
        ProjectInformation projectInfo)
    {
        new ProjectInfoBuilder(_document).AddProjectInformation(projectInfo);
        return this;
    }
    public CustomerDocumentBuilder AddFooter(
        string footerText)
    {
        new FooterBuilder(_document).AddFooter(footerText);
        return this;
    }       
    public CustomerDocumentBuilder AddPageNumbers()
    {
        new PageNumbersBuilder(_document).AddPageNumbers();
        return this;
    }
}

public class SalesReportBuilder
{
    private readonly Doc _document;

    private SalesReportBuilder()
    {
        _document = new();
    }

    public static SalesReportBuilder Create() => new();

    public void Build()
    {
        _document.Save("C:\\pdf\\textflow.pdf");
    }

    public SalesReportBuilder AddDocument(
        DocumentInformation documentInfo)
    {
        new DocumentBuilder(_document).AddDocument(documentInfo);
        return this;
    }

    public SalesReportBuilder AddFooter(
        string footerText)
    {
        new FooterBuilder(_document).AddFooter(footerText);
        return this;
    }

    public SalesReportBuilder AddPageNumbers(
        DocumentInformation documentInfo)
    {
        new PageNumbersBuilder(_document).AddPageNumbers();
        return this;
    }

}

public class CustomerBuilder : ICustomerBuilder
{
    private readonly Doc _document;

    public CustomerBuilder(
        Doc document)
    {
        _document = document;
    }

    public ICustomerBuilder AddCustomerInformation(
        CustomerInformation customerInfo)
    {
        _document.AddTextStyled(customerInfo.Name);
        // etc...
        return this;
    }
}

public class DocumentBuilder : IDocumentBuilder
{
    private readonly Doc _document;

    public DocumentBuilder(
        Doc document)
    {
        _document = document;
    }

    public IDocumentBuilder AddDocument(
        DocumentInformation documentInfo)
    {
        _document.AddTextStyled(documentInfo.Name);
        // etc...
        return this;
    }
}

public class ProjectInfoBuilder : IProjectInfoBuilder
{
    private readonly Doc _document;

    public ProjectInfoBuilder(
        Doc document)
    {
        _document = document;
    }

    public IProjectInfoBuilder AddProjectInformation(
        ProjectInformation projectInfo)
    {
        _document.AddTextStyled(projectInfo.Name);
        // etc...
        return this;
    }
}

public class FooterBuilder : IFooterBuilder
{
    private readonly Doc _document;

    public FooterBuilder(
        Doc document)
    {
        _document = document;
    }

    public IFooterBuilder AddFooter(
        string footerText)
    {
        _document.AddTextStyled(footerText);
        // etc...
        return this;
    }
}

public class PageNumbersBuilder : IPageNumbersBuilder
{
    private readonly Doc _document;

    public PageNumbersBuilder(
        Doc document)
    {
        _document = document;
    }

    public IPageNumbersBuilder AddPageNumbers()
    {
        //calculcate pages and insert
        // page number to each pages
        return this;
    }
}

public interface IDocumentBuilder
{
    IDocumentBuilder AddDocument(DocumentInformation documentInfo);
}
public interface ICustomerBuilder
{
    ICustomerBuilder AddCustomerInformation(CustomerInformation customerInfo);
}
public interface IProjectInfoBuilder
{
    IProjectInfoBuilder AddProjectInformation(ProjectInformation projectInfo);
}
public interface IFooterBuilder
{
    IFooterBuilder AddFooter(string footerText);
}
public interface IPageNumbersBuilder
{
    IPageNumbersBuilder AddPageNumbers();
}

Aucun commentaire:

Enregistrer un commentaire