Project – Adding behaviors – Structural Patterns

Let’s implement the previous example to help visualize the Decorator pattern, which adds some arbitrary behaviors. Each Operation() method returns a string that is then outputted to the response stream. It is not fancy but visually shows how the pattern works.First, let’s look at the IComponent interface:

public interface IComponent
{
    string Operation();
}

The IComponent interface only states that an implementation should have an Operation() method that returns a string.Next, let’s look at the ComponentA class:

public class ComponentA : IComponent
{
    public string Operation()
    {
        return “Hello from ComponentA”;
    }
}

The Operation() method of the ComponentA class returns a literal string.Now that we described the first pieces, let’s look at the consumer:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IComponent, ComponentA>();
var app = builder.Build();
app.MapGet(“/”, (IComponent component) => component.Operation());
app.Run();

In the Program.cs file above, we register ComponentA as the implementation of IComponent, with a singleton lifetime. We then inject an IComponent implementation when an HTTP request hits the / endpoint. The delegate then calls the Operation() method and outputs the result to the response.At this point, running the application results in the following response:

Hello from ComponentA

So far, it’s pretty simple; the client calls the endpoint, the container injects an instance of the ComponentA class into the endpoint delegate, then the endpoint returns the results of Operation method to the client.Next, we add the first decorator.

DecoratorA

Here, we want to modify the response without touching the code of the ComponentA class. To do so, we chose to create a decorator named DecoratorA that wraps the Operation() result into a <DecoratorA> tag:

public class DecoratorA : IComponent
{
    private readonly IComponent _component;
    public DecoratorA(IComponent component)
    {
        _component = component ??
throw new ArgumentNullException(nameof(component));
    }
    public string Operation()
    {
        var result = _component.Operation();
        return $”<DecoratorA>{result}</DecoratorA>”;
    }
}

DecoratorA implements and depends on the IComponent interface. It uses the injected IComponent implementation in its Operation() method and wraps its result in an HTML-like (XML) tag.Now that we have a decorator, we need to tell the IoC container to send an instance of DecoratorA instead of ComponentA when injecting an IComponent interface.DecoratorA should decorate ComponentA. More precisely, the container should inject an instance of the ComponentA class into the DecoratorA class.To achieve this, we could register it as follows:

builder.Services.AddSingleton<IComponent>(serviceProvider => new DecoratorA(new ComponentA()));

Here, we are telling ASP.NET Core to inject an instance of DecoratorA that decorates an instance of ComponentA when injecting an IComponent interface. When we run the application, we should see the following result in the browser:

<DecoratorA>Hello from ComponentA</DecoratorA>

You may have noticed a few new keywords there, but even though it is not very elegant, we can manually create new instances in the composition root without jeopardizing our application’s health. We learn how to get rid of some of them later with the introduction of Scrutor.

Next, let’s create the second decorator.

Leave a Reply

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



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