Project – Building a search machine – Behavioral Patterns-2

Now that we have defined the actors and explored the code, let’s see what is happening in our consumer (the Client):

  1. The Client uses the registered SearchMachine instances and searches for values 1, 10, and 11.
  2. Afterward, Client displays to the user whether the numbers were found or not.

The Find method returns null when it does not find a value and, by extension, the IndexOf method.By running the program, we get the following output:

=============================================
Current search machine is LinearSearchMachine
The element ‘1’ was found at index 0.
The element ’10’ was found at index 1.
The element ’11’ was not found.
=============================================
Current search machine is BinarySearchMachine
The element ‘1’ was found at index 0.
The element ’10’ was found at index 9.
The element ’11’ was not found.

The preceding output shows the two algorithms at play. Both SearchMachine implementations did not contain the value 11. They both contained the values 1 and 10 placed at different positions. Here is a reminder of the values:

new LinearSearchMachine(1, 10, 5, 2, 123, 333, 4)
new BinarySearchMachine(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

The consumer was iterating the SearchMachine registered with the IoC container. The base class implements the IndexOf but delegates the search (Find) algorithm to the subclasses. The preceding output shows that each SearchMachine could execute the expected task by implementing only the Find piece of the algorithm.And voilà! We have covered the Template Method pattern, as easy as that. Of course, our algorithm was trivial, but the concept remains.To ensure the correctness of the implementation, I also created two tests, one per class. Here’s a test for the LinearSearchMachine class:

namespace TemplateMethod;
public class LinearSearchMachineTest
{
    public class IndexOf
    {
        [Theory]
        [InlineData(1, 0)]
        [InlineData(2, 4)]
        [InlineData(3, 2)]
        [InlineData(7, null)]
        public void Should_return_the_expected_result(
            int value, int?
expectedIndex)
        {
            // Arrange
            var sorter = new LinearSearchMachine(1, 5, 3, 4, 2);
            // Act
            var index = sorter.IndexOf(value);
            // Assert
            Assert.Equal(expectedIndex, index);
        }
    }
}

The preceding test ensures that the correct values are found or not by the IndexOf method of the LinearSearchMachine class.Next is a similar test for the BinarySearchMachine class:

namespace TemplateMethod;
public class BinarySearchMachineTest
{
    public class IndexOf
    {
        [Theory]
        [InlineData(1, 0)]
        [InlineData(8, 5)]
        [InlineData(3, 2)]
        [InlineData(7, null)]
        public void Should_return_the_expected_result(int value, int?
expectedIndex)
        {
            // Arrange
            var sorter = new BinarySearchMachine(1, 2, 3, 4, 5, 8);
            // Act
            var index = sorter.IndexOf(value);
            // Assert
            Assert.Equal(expectedIndex, index);
        }
    }
}

The preceding test does a similar job of ensuring that the correct values are found or not by the IndexOf method of the BinarySearchMachine class.

We can add virtual methods in the base class to create optional hooks. Those methods would become optional extension points that subclasses can implement or not. That would allow a more complex and more versatile scenario to be supported. We will not cover this here because it is not part of the pattern itself, even if very similar. There are many examples in the .NET base class library (BCL), like most methods of the ComponentBase class (in the Microsoft.AspNetCore.Components namespace). For example, when overriding the OnInitialized method in a Blazor component, we leverage an optional extension hook. The base method does nothing and is there only for extensibility purposes, allowing us to run code as part of the component’s lifecycle. You can consult the ComponentBase class code in the official .NET repo on GitHub: https://adpg.link/1WYq.

This concludes our study of another simple yet powerful design pattern.

Leave a Reply

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



          Copyright © 2015-2024 | About | Terms of Service | Privacy Policy