Real-Time Examples of Template Method Design Pattern in C#

Real-Time Examples of Template Method Design Pattern in C#

In this article, I will discuss the Real-Time Examples of the Template Method Design Pattern in C#. Please read our previous article discussing the basic concepts of Template Method Design Patterns in C# with Examples. At the end of this article, you will understand the following Real-time Examples using Template Method Design Pattern in C#.

  1. Data Synchronization Between Source and Destination
  2. Online Shopping System
  3. Document Converter Tool
  4. Test-Taking Platforms (Online Exam)
  5. Online Food Recipes
  6. Fitness Workouts
  7. CI/CD Pipeline Execution
  8. Bank Account Operations
  9. Planning a Trip
Real-Time Example of Template Method Design Pattern in C#: Data Synchronization

Let’s take the example of a software tool that synchronizes data between a source and a destination. The steps for synchronization can be generalized as follows:

  • Open the Source Connection.
  • Open Destination Connection.
  • Read data from a source.
  • Write data to a destination.
  • Close source connection.
  • Close destination connection.

However, how you connect to, read from, or write to a source/destination can vary based on the data medium. For instance, the source could be a database, an API, a local file, etc. Using the Template Method Design Pattern, you can define the general synchronization steps and allow subclasses to define specifics. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class DataSynchronizer
    {
        public void Synchronize()
        {
            OpenSource();
            OpenDestination();
            TransferData();
            CloseSource();
            CloseDestination();
        }

        protected abstract void OpenSource();
        protected abstract void OpenDestination();
        protected abstract void TransferData();
        protected abstract void CloseSource();
        protected abstract void CloseDestination();
    }

    //Concrete Implementations:
    //For Database to File synchronization
    public class DatabaseToFileSynchronizer : DataSynchronizer
    {
        protected override void OpenSource()
        {
            Console.WriteLine("Opening database connection...");
        }

        protected override void OpenDestination()
        {
            Console.WriteLine("Opening file for writing...");
        }

        protected override void TransferData()
        {
            Console.WriteLine("Reading data from database and writing to file...");
        }

        protected override void CloseSource()
        {
            Console.WriteLine("Closing database connection...");
        }

        protected override void CloseDestination()
        {
            Console.WriteLine("Closing file...");
        }
    }

    //For API to Database synchronization
    public class ApiToDatabaseSynchronizer : DataSynchronizer
    {
        protected override void OpenSource()
        {
            Console.WriteLine("Connecting to API...");
        }

        protected override void OpenDestination()
        {
            Console.WriteLine("Opening database connection for writing...");
        }

        protected override void TransferData()
        {
            Console.WriteLine("Fetching data from API and inserting into database...");
        }

        protected override void CloseSource()
        {
            Console.WriteLine("Closing API connection...");
        }

        protected override void CloseDestination()
        {
            Console.WriteLine("Closing database connection...");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            DataSynchronizer dbToFileSync = new DatabaseToFileSynchronizer();
            dbToFileSync.Synchronize();

            Console.WriteLine();

            DataSynchronizer apiToDbSync = new ApiToDatabaseSynchronizer();
            apiToDbSync.Synchronize();

            Console.ReadKey();
        }
    }
}

In this example, the DataSynchronizer class provides the template for synchronization. The specific ways to open connections, transfer data, and close connections are provided by concrete implementations, allowing for flexibility in handling different data sources and destinations. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: Data Synchronization

Real-Time Example of Template Method Design Pattern in C#: Online Shopping System

Let’s look at another practical real-time example: an online shopping system. When a customer places an order, the general steps might be:

  • Validate payment details.
  • Deduct payment.
  • Confirm stock availability.
  • Initiate packaging.
  • Ship the product.

However, the exact details can vary based on the type of product. For example, perishable goods might need refrigerated packaging, while digital goods don’t need physical shipping. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class OrderProcessor
    {
        // The template method
        public void ProcessOrder()
        {
            ValidatePayment();
            DeductPayment();
            CheckStock();
            PackageProduct();
            Ship();
        }

        public void ValidatePayment()
        {
            Console.WriteLine("Validating payment details.");
        }

        public void DeductPayment()
        {
            Console.WriteLine("Deducting payment.");
        }

        public void CheckStock()
        {
            Console.WriteLine("Checking stock availability.");
        }

        // Abstract methods for steps that might vary across subclasses
        protected abstract void PackageProduct();
        protected abstract void Ship();
    }
    
    //Concrete Implementations:
    //For Perishable Goods
    public class PerishableGoodsOrder : OrderProcessor
    {
        protected override void PackageProduct()
        {
            Console.WriteLine("Packaging with refrigeration.");
        }

        protected override void Ship()
        {
            Console.WriteLine("Shipping with temperature control.");
        }
    }

    //For Digital Goods
    public class DigitalGoodsOrder : OrderProcessor
    {
        protected override void PackageProduct()
        {
            Console.WriteLine("Generating digital access key.");
        }

        protected override void Ship()
        {
            Console.WriteLine("Sending product download link via email.");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Processing Perishable Goods Order:");
            OrderProcessor perishableOrder = new PerishableGoodsOrder();
            perishableOrder.ProcessOrder();

            Console.WriteLine("\nProcessing Digital Goods Order:");
            OrderProcessor digitalOrder = new DigitalGoodsOrder();
            digitalOrder.ProcessOrder();

            Console.ReadKey();
        }
    }
}

The OrderProcessor class provides the general template for processing an order in this real-time example. The packaging and shipping details, which can vary based on the product type, are provided by concrete implementations (PerishableGoodsOrder and DigitalGoodsOrder). This allows flexibility in handling different product types while maintaining a consistent order processing flow. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: Online Shopping System

Real-Time Example of Template Method Design Pattern in C#: Document Converter Tool

Imagine you have a tool that converts documents from one format to another. The general process might look like this:

  • Load the source document.
  • Parse the document’s content.
  • Convert the content to the desired format.
  • Save the converted content to a new file.

The overall structure of the process remains the same, but the specifics of parsing, conversion, and saving depend on the target format, be it PDF, DOCX, TXT, etc. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class DocumentConverter
    {
        // The template method
        public void ConvertDocument(string filePath)
        {
            LoadDocument(filePath);
            ParseContent();
            ConvertToTargetFormat();
            SaveConvertedDocument();
        }

        private void LoadDocument(string filePath)
        {
            Console.WriteLine($"Loading document from {filePath}.");
        }

        protected abstract void ParseContent();
        protected abstract void ConvertToTargetFormat();
        protected abstract void SaveConvertedDocument();
    }

    //Concrete Implementations:
    //For converting to PDF
    public class PdfConverter : DocumentConverter
    {
        protected override void ParseContent()
        {
            Console.WriteLine("Parsing content for PDF conversion.");
        }

        protected override void ConvertToTargetFormat()
        {
            Console.WriteLine("Converting content to PDF format.");
        }

        protected override void SaveConvertedDocument()
        {
            Console.WriteLine("Saving document as PDF.");
        }
    }

    //For converting to TXT
    public class TxtConverter : DocumentConverter
    {
        protected override void ParseContent()
        {
            Console.WriteLine("Parsing content for TXT conversion.");
        }

        protected override void ConvertToTargetFormat()
        {
            Console.WriteLine("Converting content to plain text format.");
        }

        protected override void SaveConvertedDocument()
        {
            Console.WriteLine("Saving document as TXT.");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Converting to PDF:");
            DocumentConverter pdfConverter = new PdfConverter();
            pdfConverter.ConvertDocument("source.docx");

            Console.WriteLine("\nConverting to TXT:");
            DocumentConverter txtConverter = new TxtConverter();
            txtConverter.ConvertDocument("source.docx");

            Console.ReadKey();
        }
    }
}

In this real-time example, the DocumentConverter class defines a standard process for document conversion. However, the specifics of parsing, conversion, and saving are left to the concrete implementations (PdfConverter and TxtConverter), which handle the nuances of their respective target formats. The template method pattern allows for a streamlined conversion process that can be easily extended to support additional document formats in the future. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: Document Converter Tool

Real-Time Example of Template Method Design Pattern in C#: Test-Taking Platforms

Let’s explore the domain of test-taking platforms. Imagine an online test platform where tests have common steps but might differ in how questions are presented or evaluated based on the type of test, e.g., multiple-choice test, true/false test, or short-answer test.

  • Start the Test.
  • Display Questions.
  • Collect Responses.
  • Evaluate Responses.
  • Display Results.

Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class OnlineTest
    {
        // The template method
        public void ConductTest()
        {
            StartTest();
            DisplayQuestions();
            CollectResponses();
            EvaluateResponses();
            DisplayResults();
        }

        private void StartTest()
        {
            Console.WriteLine("Starting the test...");
        }

        protected abstract void DisplayQuestions();
        protected abstract void CollectResponses();
        protected abstract void EvaluateResponses();

        private void DisplayResults()
        {
            Console.WriteLine("Displaying test results...");
        }
    }

    //Concrete Implementations:
    //For Multiple Choice Test
    public class MultipleChoiceTest : OnlineTest
    {
        protected override void DisplayQuestions()
        {
            Console.WriteLine("Displaying multiple-choice questions.");
        }

        protected override void CollectResponses()
        {
            Console.WriteLine("Collecting choices for multiple-choice questions.");
        }

        protected override void EvaluateResponses()
        {
            Console.WriteLine("Evaluating choices for multiple-choice questions.");
        }
    }

    //For True/False Test
    public class TrueFalseTest : OnlineTest
    {
        protected override void DisplayQuestions()
        {
            Console.WriteLine("Displaying true/false questions.");
        }

        protected override void CollectResponses()
        {
            Console.WriteLine("Collecting responses for true/false questions.");
        }

        protected override void EvaluateResponses()
        {
            Console.WriteLine("Evaluating responses for true/false questions.");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Conducting Multiple Choice Test:");
            OnlineTest multipleChoiceTest = new MultipleChoiceTest();
            multipleChoiceTest.ConductTest();

            Console.WriteLine("\nConducting True/False Test:");
            OnlineTest trueFalseTest = new TrueFalseTest();
            trueFalseTest.ConductTest();

            Console.ReadKey();
        }
    }
}

In this example, the OnlineTest class provides a general framework for how a test should be conducted. Specific types of tests, such as multiple-choice or true/false tests, provide concrete implementations of how questions are displayed, responses are collected, and evaluations are made. This demonstrates the utility of the Template Method pattern in providing a structured process while allowing for specific variations based on concrete implementations. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: Test-Taking Platforms

Real-Time Example of Template Method Design Pattern in C#: Online Food Recipes

Consider an application where users can view step-by-step instructions for cooking various dishes. While all recipes will have the steps of “Preparation”, “Cooking”, and “Serving”, the specifics of each step may differ based on the dish. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class Recipe
    {
        // The template method
        public void MakeDish()
        {
            Preparation();
            Cooking();
            Serving();
        }

        protected abstract void Preparation();
        protected abstract void Cooking();
        protected abstract void Serving();
    }

    //Concrete Implementations:
    //For Pasta
    public class PastaRecipe : Recipe
    {
        protected override void Preparation()
        {
            Console.WriteLine("Boiling water, selecting pasta type, and preparing ingredients.");
        }

        protected override void Cooking()
        {
            Console.WriteLine("Cooking pasta in boiling water, preparing sauce on the side.");
        }

        protected override void Serving()
        {
            Console.WriteLine("Serving pasta with sauce and optional cheese on top.");
        }
    }

    //For Grilled Chicken
    public class GrilledChickenRecipe : Recipe
    {
        protected override void Preparation()
        {
            Console.WriteLine("Marinating the chicken with herbs and spices.");
        }

        protected override void Cooking()
        {
            Console.WriteLine("Grilling the chicken until well-cooked.");
        }

        protected override void Serving()
        {
            Console.WriteLine("Serving grilled chicken with side vegetables.");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Making Pasta:");
            Recipe pasta = new PastaRecipe();
            pasta.MakeDish();

            Console.WriteLine("\nMaking Grilled Chicken:");
            Recipe grilledChicken = new GrilledChickenRecipe();
            grilledChicken.MakeDish();

            Console.ReadKey();
        }
    }
}

The Recipe class provides a blueprint for making a dish in this real-time example. Different dishes, such as pasta or grilled chicken, fill in the specific details for each step. The Template Method pattern allows the app to have a consistent step-by-step approach for all recipes, while the specific instructions can be varied and detailed for each dish. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: Online Food Recipes

Real-Time Example of Template Method Design Pattern in C#: Fitness Workouts

Consider a fitness application that provides workout routines. While all workouts have a similar structure, such as “Warm-up”, “Main Exercise”, and “Cool Down”, the specific exercises in each phase differ based on the type of workout. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class WorkoutRoutine
    {
        // The template method
        public void PerformWorkout()
        {
            WarmUp();
            MainExercise();
            CoolDown();
        }

        protected virtual void WarmUp()
        {
            Console.WriteLine("General stretching and light jogging.");
        }
        protected abstract void MainExercise();
        protected virtual void CoolDown()
        {
            Console.WriteLine("General stretching and deep breathing.");
        }
    }

    //Concrete Implementations:
    //For Cardio Routine
    public class CardioRoutine : WorkoutRoutine
    {
        protected override void MainExercise()
        {
            Console.WriteLine("Performing 30 minutes of high-intensity interval training.");
        }
    }

    //For Strength Training
    public class StrengthTrainingRoutine : WorkoutRoutine
    {
        protected override void MainExercise()
        {
            Console.WriteLine("Performing 4 sets of weight lifting exercises targeting different muscle groups.");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Cardio Workout:");
            WorkoutRoutine cardio = new CardioRoutine();
            cardio.PerformWorkout();

            Console.WriteLine("\nStrength Training Workout:");
            WorkoutRoutine strengthTraining = new StrengthTrainingRoutine();
            strengthTraining.PerformWorkout();

            Console.ReadKey();
        }
    }
}

In this real-world example, the WorkoutRoutine class provides the general structure of a workout. Different workouts, like cardio and strength training, implement the specifics of the main exercise phase. The Template Method pattern allows the application to maintain a standard structure for workouts, with flexibility in the specific exercises based on the workout type. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: Fitness Workouts

Real-Time Example of Template Method Design Pattern in C#: CI/CD Pipeline Execution

Let’s understand the example of software development with the continuous integration and deployment (CI/CD) process. Most CI/CD pipelines have the following stages:

  • Checkout Code.
  • Run Tests.
  • Build Artifacts.
  • Deploy.

However, the exact tools or processes involved might differ based on the project type. Let’s consider two types of projects: a “Web Application” and a “Library Package”. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class CICDPipeline
    {
        // Template method
        public void ExecutePipeline()
        {
            CheckoutCode();
            RunTests();
            BuildArtifacts();
            Deploy();
        }

        private void CheckoutCode()
        {
            Console.WriteLine("Checking out code from version control...");
        }

        protected abstract void RunTests();
        protected abstract void BuildArtifacts();
        protected abstract void Deploy();
    }

    //Concrete Implementations:
    //For Web Application
    public class WebAppPipeline : CICDPipeline
    {
        protected override void RunTests()
        {
            Console.WriteLine("Running web app unit and integration tests...");
        }

        protected override void BuildArtifacts()
        {
            Console.WriteLine("Building web application binaries and assets...");
        }

        protected override void Deploy()
        {
            Console.WriteLine("Deploying web application to server...");
        }
    }

    //For Library Package
    public class LibraryPackagePipeline : CICDPipeline
    {
        protected override void RunTests()
        {
            Console.WriteLine("Running library unit tests...");
        }

        protected override void BuildArtifacts()
        {
            Console.WriteLine("Building library binaries...");
        }

        protected override void Deploy()
        {
            Console.WriteLine("Publishing library to package repository...");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Executing CI/CD for Web Application:");
            CICDPipeline webAppPipeline = new WebAppPipeline();
            webAppPipeline.ExecutePipeline();

            Console.WriteLine("\nExecuting CI/CD for Library Package:");
            CICDPipeline libraryPipeline = new LibraryPackagePipeline();
            libraryPipeline.ExecutePipeline();

            Console.ReadKey();
        }
    }
}

In this example, the CICDPipeline class provides a generalized framework for executing a CI/CD process. The concrete implementations (WebAppPipeline and LibraryPackagePipeline) fill in the specifics of how tests are run, artifacts are built, and deployments are made for the two types of projects. The Template Method pattern ensures a consistent pipeline execution flow, allowing tailored processes for each project type. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: CI/CD Pipeline Execution

Real-Time Example of Template Method Design Pattern in C#: Bank Account Operations

Let’s consider the domain of financial transactions, focusing on bank account operations. While performing operations on a bank account, most of the operations follow a standard set of steps. For example, in withdrawing and depositing funds, it’s necessary to log in, validate the account, perform the operation, and log the transaction. However, the specifics of the “perform operation” step would differ based on whether it’s a withdrawal or deposit. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class BankOperation
    {
        // Template method
        public void ExecuteOperation()
        {
            Login();
            ValidateAccount();
            PerformOperation();
            LogTransaction();
        }

        private void Login()
        {
            Console.WriteLine("Logging into the bank system...");
        }

        private void ValidateAccount()
        {
            Console.WriteLine("Validating account credentials...");
        }

        protected abstract void PerformOperation();

        private void LogTransaction()
        {
            Console.WriteLine("Logging the transaction details...");
        }
    }

    //Concrete Implementations:
    //For Withdrawal
    public class WithdrawFunds : BankOperation
    {
        private double amount;

        public WithdrawFunds(double amount)
        {
            this.amount = amount;
        }

        protected override void PerformOperation()
        {
            Console.WriteLine($"Withdrawing ${amount} from the account...");
        }
    }

    //For Deposit
    public class DepositFunds : BankOperation
    {
        private double amount;

        public DepositFunds(double amount)
        {
            this.amount = amount;
        }

        protected override void PerformOperation()
        {
            Console.WriteLine($"Depositing ${amount} to the account...");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Executing Withdrawal Operation:");
            BankOperation withdrawal = new WithdrawFunds(100);
            withdrawal.ExecuteOperation();

            Console.WriteLine("\nExecuting Deposit Operation:");
            BankOperation deposit = new DepositFunds(150);
            deposit.ExecuteOperation();

            Console.ReadKey();
        }
    }
}

In this real-world example, the BankOperation class defines the overall flow for executing a bank transaction. The concrete implementations (WithdrawFunds and DepositFunds) provide specific withdrawal and deposit operations steps. The Template Method pattern ensures that the sequence of operations is adhered to while allowing the flexibility to vary the core transaction step based on the operation type. When you run the above code, you will get the following output.

Real-Time Examples of Template Method Design Pattern in C#

Real-Time Example of Template Method Design Pattern in C#: Planning a Trip

Every trip, be it a business trip or a vacation, usually involves a sequence of steps like deciding the destination, booking transportation, reserving accommodations, packing, and finally setting off. However, the details of some of these steps differ based on the nature of the trip. Let us see how we can implement the above example using the Template Method Design Pattern in C#:

using System;
namespace TemplateMethodDesignPattern
{
    //Abstract Class(Template)
    public abstract class TripPlanner
    {
        // Template method
        public void PlanTrip()
        {
            DecideDestination();
            BookTransport();
            ReserveAccommodations();
            Pack();
            BeginJourney();
        }

        private void DecideDestination()
        {
            Console.WriteLine("Deciding the destination...");
        }

        protected abstract void BookTransport();
        protected abstract void ReserveAccommodations();

        private void Pack()
        {
            Console.WriteLine("Packing essentials for the trip...");
        }

        private void BeginJourney()
        {
            Console.WriteLine("Setting off for the journey...");
        }
    }

    //Concrete Implementations:
    //For Business Trip
    public class BusinessTrip : TripPlanner
    {
        protected override void BookTransport()
        {
            Console.WriteLine("Booking a business class flight ticket...");
        }

        protected override void ReserveAccommodations()
        {
            Console.WriteLine("Reserving a room in a business hotel...");
        }
    }

    //For Vacation Trip
    public class VacationTrip : TripPlanner
    {
        protected override void BookTransport()
        {
            Console.WriteLine("Booking economy class flight or train tickets...");
        }

        protected override void ReserveAccommodations()
        {
            Console.WriteLine("Reserving a beach resort or a vacation rental...");
        }
    }
    
    // Testing the Template Method Design Pattern
    // Client Code
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Planning a Business Trip:");
            TripPlanner businessTrip = new BusinessTrip();
            businessTrip.PlanTrip();

            Console.WriteLine("\nPlanning a Vacation Trip:");
            TripPlanner vacation = new VacationTrip();
            vacation.PlanTrip();

            Console.ReadKey();
        }
    }
}

The TripPlanner class provides a generalized trip planning sequence in this real-time example. The concrete implementations (BusinessTrip and VacationTrip) define the specifics of booking transportation and reserving accommodations based on the type of trip. The Template Method pattern ensures a structured approach to trip planning while allowing customization for different types of trips. When you run the above code, you will get the following output.

Real-Time Example of Template Method Design Pattern in C#: Planning a Trip

When to use Template Method Design Patterns in Real-Time Applications?

The Template Method Design Pattern is useful in real-time applications when:

  • Algorithm Structure is Invariant, but Implementation Varies: The pattern is ideal when the steps of an algorithm are set in a particular sequence, but the implementation of some steps might differ across different contexts.
  • Code Reusability: When there’s a need to avoid code duplication, the same basic algorithm structure is used across multiple places but with different nuances.
  • Subclassing: When you want to let clients extend only certain parts of a large algorithm, ensure the structure remains consistent.
  • Localizing Common Behavior: Certain behaviors or processes are common across subclasses, but some specific steps might need to be specialized. The common behavior can be factored into a single location in the base class.

Here are some real-world scenarios where the Template Method pattern can be employed:

  • Data Processing Pipelines: Often, data needs to go through a fixed set of processing steps, such as validation, transformation, and aggregation. While the sequence of steps remains consistent, the details of each step might vary. The Template Method pattern can define this pipeline.
  • Application Frameworks: Many software frameworks use the Template Method pattern to provide hooks for developers. For example, in many web frameworks, there’s a sequence of events like “before request”, “handle request”, and “after request”. Developers can provide custom behavior at these hooks without changing the request-handling framework.
  • Cooking Recipe: Imagine a cooking application where every recipe has a similar structure – preparation, cooking, and serving. The template can define this structure, while subclasses can provide the specifics for each recipe.
  • Report Generators: Systems that generate reports can have a fixed structure, like fetching data, formatting data, and then rendering or exporting it. Depending on the type of report, the fetching and formatting logic might vary, making this a good fit for the Template Method pattern.
  • Gaming Systems: In games, especially strategy games, turn-based systems might have a fixed structure (e.g., start of turn, main phase, battle phase, end of turn). The specifics of what happens in each phase might vary based on gameplay or characters, making the Template Method useful.
  • Workflow Systems: Workflow engines often have tasks that must be executed in a specific sequence. While the overall flow might be consistent, specific task implementations can vary.

When using the Template Method pattern, it’s important to ensure that you don’t make the system too rigid. Providing too few “hook” methods can limit flexibility, while too many can confuse the system. It’s about striking the right balance. So, we need to use the Template Method Design Pattern in Real-Time Applications when

  1. We have a method in the base class that calls many other methods that are either abstract or empty in a particular sequence.
  2. We required an abstract view of an algorithm, but the implementation of the algorithm varies according to the child classes.
Advantages and Disadvantages of Template Method Design Pattern in C#

The Template Method Design Pattern offers various advantages and disadvantages:

Advantages:
  1. Code Reusability: By encapsulating the invariant parts of the algorithm in the base class, there’s less code duplication. Subclasses must only implement the varying parts, leading to cleaner and more maintainable code.
  2. Flexibility: The pattern provides a clear structure by defining specific steps in the algorithm that can be overridden. This lets subclasses redefine or extend specific parts without changing the algorithm’s structure.
  3. Consistency: By enforcing a specific sequence of steps in the base class, the pattern ensures that the algorithm’s structure remains consistent across all subclasses.
  4. Localization of Changes: If you need to modify a step’s behavior across all subclasses, you can make that change in the base class. This localized change ensures consistency and reduces errors.
  5. Framework Design: Template Method is often used in framework designs where the framework controls how something should be done, but the exact details are left to the implementers.
Disadvantages:
  1. Rigidity in Structure: The base class defines the main sequence and cannot be changed by subclasses. If there’s a need to change the sequence for some scenarios, the Template Method pattern might not be the best fit.
  2. Overhead for Simple Implementations: If some subclasses have a straightforward implementation or don’t require all the steps provided by the template method, there might be an unnecessary overhead in following the structure.
  3. Class Explosion: A new subclass must be created for each algorithm variation. If there are many variations, this can lead to a proliferation of classes.
  4. Tight Coupling: The pattern can lead to tight coupling between the base class and subclasses. Changes in the base class can ripple through to the subclasses, leading to potential issues.
  5. Lack of Runtime Flexibility: The steps and their sequence are fixed at compile time. If there’s a need for dynamic determination of steps or their sequence at runtime, the Template Method may not be the right choice.

In conclusion, while the Template Method pattern can be a powerful tool in certain scenarios, like any design pattern, its appropriateness depends on the problem being addressed. One should weigh the advantages against the disadvantages to decide if it fits a particular situation well.

In the next article, I will discuss the Command Design Pattern in C# with Examples. Here, in this article, I try to explain Real-Time Examples of Template Method Design Patterns in C#. I hope you enjoy this Template Method Design Pattern Real-Time Example article.

2 thoughts on “Real-Time Examples of Template Method Design Pattern in C#”

  1. Brilliantly explained that now I can figure out the problem in my project and improve it using this design pattern.

  2. coffee.PrepareCoffee doesn’t make sense in the real world.
    NescafeTemplate or NescafeMakerTemplate sounds better to me.
    e.x)
    nescafeTemplate.MakeProduct() : Nescafe
    The single responsibility of the template is now a CoffeeMaker, so we need to write new classes derived from a superclass Coffee.

Leave a Reply

Your email address will not be published. Required fields are marked *