---
title: "Decorator Pattern using the example of a cached repository"
description: "The decorator pattern is a common pattern in object oriented languages. It allows us to add behavior to an individual object without changing the object itself.\n\nWe will exactly that with a repository. We introduce a caching layer via the decorator pattern."
updated: 2022-02-19
tags: ["C#", "Repository", "Pattern", "Decorator"]
canonical: "https://steven-giesel.com/blogPost/35df92c5-d5dd-488b-9b6b-25ed12c0420e/decorator-pattern-using-the-example-of-a-cached-repository"
---

# Decorator Pattern using the example of a cached repository

The **decorator pattern** allows you to add (dynamically) behavior to an individual object without affecting the [behavior](https://en.wikipedia.org/wiki/Decorator_pattern). It helps you with the *Single Responsibility* principle (see [SOLID principles](https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design)). It also adheres the famous quote: "Favor composition over inheritance". So it's a nice way of avoiding subclassing and still add [extended functionaility](http://w3sdesign.com/?gr=s04&ugr=proble).

Typically you have at least 3 components: An **interface**, an **concrete implementation** and the **decorator** itself. The following picture will show you how they correlate to each other.

![pattern](https://linkdotnetblog.azureedge.net/blog/20220219_DecoratorPattern/DecoratorAbstract.svg)

The **decorator** as well as the **concrete implementation** both implement the **interface component**. But the **decorator** also has the **concrete implementation** as a field. What this allows is very simple:
 * The outside world has no idea that we are a decorator, they will always see a `interface component`
 * We have extension points before and after the call of `operation` from the`concrete implementation`

## Cached Repository
Initially I talked about creating a cached repository. This is just one of many applications for that pattern. Another one would be logging. As we can intercept before and after the "real" call, we have the ability to log for example the request and the response given from our concrete implementation. Back to our caching repository.

The idea is simple: We have an `interface IRepository` which is our contract to the outer world. We need a implementation provided by `class SlowRepository` and the decorator `class CachedRepository`:

![uml cached](https://linkdotnetblog.azureedge.net/blog/20220219_DecoratorPattern/DecoratorCachedRepository.svg)

Why `SlowRepository`? You will see in a minute.
First the easy part: Our contract `IRepository`:
```csharp
public interface IRepository  
{  
  public Task<Person> GetPersonByIdAsync(int id);  
  
  public Task SavePersonAsync(Person person);  
}
```
 
 We will use exact this interface in our sample in combination with a DI-Container. We build a new `Person` object and put it into the repository. Afterwards we load from that exact some repository the person with the Id 1.
 ```csharp
 var person = new Person(1, "Steven Giesel");  
var repository = provider.GetRequiredService<IRepository>();  
await repository.SavePersonAsync(person);  
  
var stopwatch = Stopwatch.StartNew();  
await repository.GetPersonByIdAsync(1);  
Console.WriteLine($"First call took {stopwatch.ElapsedMilliseconds} ms");  
  
stopwatch.Restart();  
await repository.GetPersonByIdAsync(1);  
Console.WriteLine($"Second call took {stopwatch.ElapsedMilliseconds} ms");
 ```
Now before we can run this, we need a real implementation and now you will see why I called it `SlowRepository`:
```csharp
public class SlowRepository : IRepository
{
    private readonly List<Person> _people = new();

    public async Task<Person> GetPersonByIdAsync(int id)
    {
        await Task.Delay(1000);
        return _people.Single(p => p.Id == id);
    }

    public Task SavePersonAsync(Person person)
    {
        _people.Add(person);
        return Task.CompletedTask;
    }
}
```

Everytime we call `GetPersonByIdAsync` we will wait 1 second before we return the object. Of course this is for demonstrational purposes.
Now we will go the last bit: the **decorator** itself. I will show you the code first and go through afterwards:
```csharp
public class CachedRepository : IRepository
{
    private readonly IMemoryCache _memoryCache;
    private readonly IRepository _repository;

    public CachedRepository(IMemoryCache memoryCache, IRepository repository)
    {
        _memoryCache = memoryCache;
        _repository = repository;
    }

    public async Task<Person> GetPersonByIdAsync(int id)
    {
        if (!_memoryCache.TryGetValue(id, out Person value))
        {
            value = await _repository.GetPersonByIdAsync(id);
            _memoryCache.Set(id, value);
        }

        return value;
    }

    public Task SavePersonAsync(Person person)
    {
        return _repository.SavePersonAsync(person);
    }
}
```

* The `CachedRepository` also implements `IRepository`
* It receives `IMemoryCache` from the DI-Container to do the caching for use
* We also receive an `IRepository` from the DI-Container which we will use later. We don't know that this is `SlowRepository`
* `GetPersonByIdAsync` checks the `IMemoryCache` if it has a value with the given id. If not, go to our `IRepository` and get the person via `GetPersonByIdAsync`. Store this in our cache and return the value. If the cache has this id, we can directly return the person from the cache. No need to go to the real repository at all!
* `SavePersonAsync` just calls `SavePersonAsync` from the "real" repository. Of course we could populate the cache here as well. But I didn't want to :D ... also for the sake of demonstration.

Now let's recap here before we continue. Our decorator acts as a [Proxy](https://stackoverflow.com/questions/18618779/differences-between-proxy-and-decorator-pattern) for the real type. With that we can control what happens right before and after the real call to the object. In our `CachedRepository` case, we use the before aspect to check whether or not a cache is populated with the asked object. If so return it from the cache, otherwise retrieve from the real implementation and populate our cache.

## Results
Lets revisit our snippet from the top. What do you think is the output on the console?
```csharp
var person = new Person(1, "Steven Giesel");
var repository = provider.GetRequiredService<IRepository>();
await repository.SavePersonAsync(person);

var stopwatch = Stopwatch.StartNew();
await repository.GetPersonByIdAsync(1);
Console.WriteLine($"First call took {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
await repository.GetPersonByIdAsync(1);
Console.WriteLine($"Second call took {stopwatch.ElapsedMilliseconds} ms");
```

Prints:

```no-class
First call took 1023 ms
Second call took 0 ms
```

So what happens on the first call:
 * First we enter our `CachedRepository` and check if the cache has an entry with the Id 1
 * As it does not have any object it calls the real `SlowRepository` to retrieve the item
 * This retrieving takes 1 second thanks to `Task.Delay(1000)` in `SlowRepository`
 * We put this item in our cache and return it to the caller


What happens on the second call:
 * We enter again our `CachedRepository` and check if the cache has an entry with the Id 1
 * But now we have an entry
 * Therefore we **don't** go to the `SlowRepository` and directly return our cached object

That is all the magic we used. We clearly divided the responsibilities and this approach is super unit testable!
Now there is only one part missing. Connecting all the things together:

## DI - Optional
In my example earlier with the stopwatch I showed that I only use `IRepository`. Also my `CachedRepository` only uses `IRepository`. Now when you want to use this with DI you have to connect all the dots on your own.
As I used a console application I installed those two packages: `Microsoft.Extensions.DependencyInjection` for the DI-Container. This is the default when you create a new ASP.NET Core project and `Microsoft.Extensions.Caching.Memory` for the `MemoryCache`.

Here the code for the DI-Container:
```csharp
var provider = new ServiceCollection()
    .AddMemoryCache()
    .AddScoped<SlowRepository>()
    .AddScoped<IRepository>(p =>

    {
        var memoryCache = p.GetRequiredService<IMemoryCache>();
        var repository = p.GetRequiredService<SlowRepository>();
        return new CachedRepository(memoryCache, repository);
    })
    .BuildServiceProvider();
```
 * `AddMemoryCache` adds the `IMemoryCache` to the container
 * `AddScoped<SlowRepository>` adds the `SlowRepository` to the container
 * The next block says: "Hey let's register our `CachedRepository` as `IRepository` into the container. I have to resolve all the dependencies for a simple reason. My `CachedRepository` wants a `IRepository` as second parameter. But there is no object right now in the dependency graph which fulfills that. Therefore I have to do this manually.
 * Of course registering `SlowRepository` into the container and getting it out a line afterwards seems strange and I could just use `return new CachedRepository(memoryCache, new SlowRepository());` but keep in mind that if your `SlowRepository` has a new constructor dependency you also have to adopt that piece of code here. Not so great.

## Resources
As always you'll find [this example](https://github.com/linkdotnet/BlogExamples/tree/main/DecoratorPattern) on my github repository where I host [the majority of my samples](https://github.com/linkdotnet/BlogExamples).

## Epilog
Now it is quite debatable if the shown example is the decorator pattern or proxy pattern. From a structural point of view both are very very similar. It depends on your definition of those where you would classify the given example ;)