Quote of the Day

more Quotes

Categories

Buy me a coffee

Template method example

Published October 31, 2021 in Design Patterns - 0 Comments

In a project I work on, I need to programmatically fill out some PDF forms. The forms are very similar in terms of structure, content, and fields’ names. Using iTextSharp library, I can go through the fields in the PDF and set the values. The logic for filling out a PDF form can be generic, as I just need to know what are the fields’ names and the corresponding values of the PDF. I come up with a generic model and common logic for filing out the form, as demonstrated in the below snippets.

public abstract class PDFService<T> where T : class {
   
   public abstract IDictionary<string, PdfFormFieldModel> ToFormDict(T formModel);


   public virtual Stream FillPdf(PDFForm<T> formFillingRequest)
        {
           // ...codes omitted for brevity. 

                foreach (KeyValuePair<string, PdfFormFieldModel> entry in ToFormDict(formFillingRequest.Content as T))
                {
                    // use iTextSharp to loop through the fields and set the corresponding values. 
                }
        }
}

The PdfFormFieldModel is just a POCO to encapsulate a field in a PDF.

public class PdfFormFieldModel
    {
        public bool IsVisible { get; set; }
        public string Name { get; set; }
        public FieldType Type { get; set; }

        public string Value { get; set; }

        public PdfFormFieldModel(string fieldName)
        {
            Name = fieldName;
        }

        public PdfFormFieldModel(string fieldName, FieldType fieldType)
        {
            Name = fieldName;
            Type = fieldType;
        }

        public PdfFormFieldModel(string name, string value) : this(name, FieldType.STRING, value)
        {
        }

        public PdfFormFieldModel(string name, FieldType type, string value) : this(name, type)
        {
            Value = value;
            IsVisible = true;
        }
    }

For each of the two forms, I create a subclass in which I override the ToFormDictionary() method to return the dictionary of which the keys represent the fields’ names in the PDF and the values represent the values to set in those fields.

Below show example snippets of the subclasses.

public class FormAPdfService : PDFService<FormA> {
     public override IDictionary<string, PdfFormFieldModel> ToFormDict(FormA form)
        {
            IDictionary<string, PdfFormFieldModel> fieldDict = new Dictionary<string, PdfFormFieldModel>();
            fieldDict.Add("Email", new PdfFormFieldModel("Email", form.Email));
            // ... codes omitted for brevity 
            return fieldDict; 
        }

}

public class FormBPdfService : PDFService<FormB> {
     public override IDictionary<string, PdfFormFieldModel> ToFormDict(FormB form)
        {
            IDictionary<string, PdfFormFieldModel> fieldDict = new Dictionary<string, PdfFormFieldModel>();
            fieldDict.Add("Name", new PdfFormFieldModel("Name", formB.Name));
            // ... codes omitted for brevity 
            return fieldDict; 
        }

}

I have followed the template method design pattern. The PDFService defines the FillPDF method, which is the template method. The abstract ToFormDict() method is for the subclasses to override to provide the data for the algorithm.

Template Method

A template method defines an algorithm in terms of abstract operations that subclasses override to provide concrete behavior.

Gamma, E., Helm, R., Johnson, R. E., & Vlissides, J. (2016). TEMPLATE METHOD. In Design patterns: Elements of reusable object-oriented software (pp. 325–326). essay, Addison-Wesley.

References

Design Patterns: Elements of Reusable Object-Oriented Software

Template Method

No comments yet