Introdução
Uma das vantagens do ASP.NET Core é a sua capacidade de usar injeção de dependência para gerenciar serviços e componentes. No entanto, às vezes você pode precisar adicionar funcionalidades adicionais a esses serviços sem modificar seu código. É aí que o Decorator Pattern entra em jogo, e uma ótima maneira de implementá-lo é usando a biblioteca Scrutor.
Decorator Pattern
O Decorator Pattern é um padrão de design estrutural que permite adicionar comportamento adicional a um objeto existente, sem modificar sua estrutura. Isso é feito criando classes decoradoras que envolvem o objeto original e adicionam as funcionalidades desejadas.
Scrutor
O Scrutor é uma biblioteca para facilitar a implementação do Decorator Pattern ao injetar serviços em tempo de execução. Ele fornece uma maneira simples e limpa de adicionar funcionalidades a serviços existentes.
Implementando o Decorator Pattern com Scrutor
Vamos dar uma olhada em como implementar o Decorator Pattern com o Scrutor em um exemplo prático.
Suponha que você tenha um repositório IClienteRepositorio
que realiza operações relacionadas a Clientes em sua API. Você deseja adicionar uma camada de cache a esse serviço sem modificar seu código existente.
1. Crie uma Interface do seu Repositório de Clientes: Essa interface é usada para representar um repositório de clientes, onde você pode buscar um cliente por seu ID.
public interface IClienteRepositorio
{
Task<Cliente?> ObterPorIdAsync(int id);
}
2. Implemente a Interface do Repositório: Esta classe ClienteRepositorio
implementa a interface IClienteRepositorio
e fornece uma implementação para o método ObterPorIdAsync
, que busca um cliente pelo seu ID em um contexto de banco de dados.
public class ClienteRepositorio : IClienteRepositorio
{
private readonly AppDbContexto _appDbContexto;
public ClienteRepositorio(AppDbContexto appDbContexto)
{
_appDbContexto = appDbContexto;
}
public async Task<Cliente?> ObterPorIdAsync(int id)
{
return await _appDbContexto
.Set<Cliente>()
.FirstOrDefaultAsync(cliente => cliente.ClienteId == id);
}
}
3. Crie a Classe do Decorator: Essa classe será a implementação do Cache. Ela deverá implementar a interface original do repositório de Clientes. Para simplificar o exemplo, vou utilizar o próprio serviço de Cache em memória do Asp.Net Core, o IMemoryCache
public class ClienteCacheRepositorio : IClienteRepositorio
{
private readonly IClienteRepositorio _clienteRepositorio;
private readonly IMemoryCache _memoryCache;
public ClienteCacheRepositorio(IClienteRepositorio clienteRepositorio,
IMemoryCache memoryCache)
{
_clienteRepositorio = clienteRepositorio;
_memoryCache = memoryCache;
}
public async Task<Cliente?> ObterPorIdAsync(int id)
{
var chave = $"cliente-{id}";
return await _memoryCache.GetOrCreateAsync(chave, async cacheEntry =>
{
cacheEntry.SetAbsoluteExpiration(TimeSpan.FromMinutes(5));
return await _clienteRepositorio.ObterPorIdAsync(id);
});
}
}
4. Instale o pacote Scrutor: você pode usar o gerenciador de pacotes NuGet com o seguinte comando: dotnet add package Scrutor
.
5. Configure a Injeção de Dependência com o Scrutor: No Program.cs
, configure a injeção de dependência para usar a classe do Decorator quando o IClienteRepositorio
for solicitado.
builder.Services.AddMemoryCache();
builder.Services.AddScoped<IClienteRepositorio, ClienteRepositorio>();
builder.Services.Decorate<IClienteRepositorio, ClienteCacheRepositorio>();
Testando a implementação
Podemos validar o funcionamento do padrão Decorator com o Scrutor através do Debug. Se colocarmos um breakpoint na implementação do método ObterPorIdAsync
, ele será executado apenas na primeira vez. Na segunda chamada, será utilizado o Memory Cache.
Podemos verificar o resultado através do tempo de resposta no Postman. Na primeira chamada da API, obtemos o cliente com o código "1". O tempo de resposta foi de 413 ms.
Na segunda chamada, podemos perceber a diferença no tempo de resposta, que foi de 10 ms, pois ele estava utilizando o cache de memória.
Conclusão
O Decorator Pattern é uma ferramenta poderosa para adicionar funcionalidades a objetos sem modificar seu código existente. Com o Scrutor em ASP.NET Core, você pode implementar facilmente o padrão Decorator ao injetar serviços em tempo de execução. Isso permite que você mantenha seu código limpo, modular e facilmente extensível.
Em resumo, os benefícios do Decorator Pattern são:
- Flexibilidade: Permite adicionar funcionalidades extras a objetos sem modificar seu código original.
- Manutenção Simples: Facilita a manutenção e evita classes excessivamente complexas.
- Composição Dinâmica: Permite combinar funcionalidades de maneira flexível.
- Reutilização de Código: Os decoradores podem ser reutilizados em diferentes partes do sistema.
- Segregação de Responsabilidades: Mantém as classes com responsabilidades únicas.
- Adere aos Princípios SOLID: Segue princípios de design de software sólidos.
- Escalabilidade: Facilita a adição de novas funcionalidades sem alterar o código existente.
Top comments (0)