DEV Community

Everton Andrade
Everton Andrade

Posted on • Edited on

2 1

Design Pattern Adapter em C#

O design pattern Adapter é um padrão de projeto do tipo estrutural que permite que interfaces incompatíveis funcionem juntas. Fazendo isso, permitimos que objetos de diferentes interfaces se comuniquem.

Neste artigo, vamos aprender como implementar o padrão Adapter em nosso projeto e quando devemos usá-lo.

Este artigo está dividido nas seguintes seções:

  • Projeto Inicial
  • Implementação do Adapter
  • Quando usar o Adapter
  • Conclusão

Projeto Inicial

Vamos imaginar que temos uma funcionalidade na qual convertemos uma lista de fabricantes de automóveis para o formato JSON e a escrevemos na tela. Mas, em vez de uma lista, foi fornecida uma API que nos fornece todos os fabricantes no formato XML.

Digamos que não possamos modificar a funcionalidade da API existente (por causa de restrições técnicas, como ser importado para o nosso projeto de outra solução que não devemos modificar ou como um pacote NuGet), então temos que encontrar uma maneira de contornar isso.

E a maneira correta de fazer isso é implementar o padrão Adapter para resolver esse problema.

Vamos começar com a criação de uma classe de modelo Manufacturer (fabricante) e um exemplo simples de objeto para conversor XML:

public class Manufacturer
{
        public string Name { get; set; }
        public string City { get; set; }
        public int Year { get; set; }
}
Enter fullscreen mode Exit fullscreen mode
public static class ManufacturerDataProvider
{
    public List<Manufacturer> GetData() =>
       new List<Manufacturer>
       {
            new Manufacturer { City = "Italy", Name = "Alfa Romeo", Year = 2016 },
            new Manufacturer { City = "UK", Name = "Aston Martin", Year = 2018 },
            new Manufacturer { City = "USA", Name = "Dodge", Year = 2017 },
            new Manufacturer { City = "Japan", Name = "Subaru", Year = 2016 },
            new Manufacturer { City = "Germany", Name = "BMW", Year = 2015 }
       };
}
Enter fullscreen mode Exit fullscreen mode
public class XmlConverter
{
    public XDocument GetXML()
    {
        var xDocument = new XDocument();
        var xElement = new XElement("Manufacturers");
        var xAttributes = ManufacturerDataProvider.GetData()
            .Select(m => new XElement("Manufacturer", 
                                new XAttribute("City", m.City),
                                new XAttribute("Name", m.Name),
                                new XAttribute("Year", m.Year)));

        xElement.Add(xAttributes);
        xDocument.Add(xElement);

        Console.WriteLine(xDocument);

        return xDocument;
    }
}
Enter fullscreen mode Exit fullscreen mode

Como podemos ver, este é um código bastante simples. Estamos coletando dados do fabricante, criando um elemento raiz do fabricante e todos os subelementos do fabricante com seus atributos.

Depois disso, estamos imprimindo os resultados na janela do console para mostrar a aparência do XML final.

Esta é a aparência do xDocument :

Saída

Agora vamos implementar uma classe JsonConverter:

public class JsonConverter
{
    private IEnumerable<Manufacturer> _manufacturers;

    public JsonConverter(IEnumerable<Manufacturer> manufacturers)
    {
        _manufacturers = manufacturers;
    }

    public void ConvertToJson()
    {
        var jsonManufacturers = JsonConvert.SerializeObject(_manufacturers, Formatting.Indented);

        Console.WriteLine("\nPrinting JSON list\n");
        Console.WriteLine(jsonManufacturers);
    }
}
Enter fullscreen mode Exit fullscreen mode

Este código é ainda mais simples porque apenas serializamos nossa lista de fabricantes em um formato JSON.

Claro, para que a serialização funcione, precisamos instalar a biblioteca Newtonsoft.Json, então não se esqueça de instala-la.

Excelente, temos nossa funcionalidade JSON e a interface XML fornecida. Mas agora, precisamos resolver um problema real. Como combinar essas duas interfaces para realizar nossa tarefa, que é converter fabricantes do formato XML para JSON.

Implementação do Adapter

Como podemos ver neste caso, não há nenhuma maneira de passar um xDocument para a classe JsonConverter e não deveria haver. Então precisamos criar a classe adapter que fará com que essas duas interfaces funcionem juntas.

Para fazer isso, vamos começar criando uma interface IXmlToJson para definir o comportamento de nossa classe adapter:

public interface IXmlToJson
{
    void ConvertXmlToJson();
}
Enter fullscreen mode Exit fullscreen mode

E então, vamos continuar com a classe XmlToJsonAdapter que implementará a interface IXmlToJson:

public class XmlToJsonAdapter : IXmlToJson
{
    private readonly XmlConverter _xmlConverter;

    public XmlToJsonAdapter(XmlConverter xmlConverter)
    {
        _xmlConverter = xmlConverter;
    }

    public void ConvertXmlToJson()
    {
        var manufacturers = _xmlConverter.GetXML()
                .Element("Manufacturers")
                .Elements("Manufacturer")
                .Select(m => new Manufacturer
                             {
                                City = m.Attribute("City").Value,
                                Name = m.Attribute("Name").Value,
                                Year = Convert.ToInt32(m.Attribute("Year").Value)
                             });

        new JsonConverter(manufacturers)
            .ConvertToJson();
    }
}
Enter fullscreen mode Exit fullscreen mode

Excelente. Criamos nossa classe adapter que converte o objeto de documento Xml na lista de fabricantes e fornece essa lista para a classe JsonConverter.

Portanto, como você pode ver, habilitamos a compatibilidade entre duas interfaces completamente diferentes apenas introduzindo uma classe adapter em nosso projeto.

Agora, podemos fazer uma chamada para esta classe adapter da nossa classe de cliente:

public class Program
{
   public static void Main(string[] args)
    {
        var xmlConverter = new XmlConverter();
        var adapter = new XmlToJsonAdapter(xmlConverter);
        adapter.ConvertXmlToJson();
    }
}
Enter fullscreen mode Exit fullscreen mode

Assim que iniciarmos nosso aplicativo, veremos o seguinte resultado:

Saída

Muito legal, não é?

E assim Concluímos nossa implementação.

Quando usar o Adapter

Devemos usar uma classe Adapter sempre que quisermos trabalhar com uma classe existente, mas que sua interface não é compatível com o resto do nosso código. Basicamente, o padrão Adapter é uma camada intermediária que serve como um tradutor entre o código implementado em nosso projeto e alguma classe de terceiros ou qualquer outra classe com uma interface diferente.

Além disso, devemos usar o Adapter quando quisermos reutilizar classes existentes de nosso projeto, quando elas não possuem uma funcionalidade comum. Ao usar o padrão Adapter neste caso, não precisamos estender cada classe separadamente e criar um código redundante.

Conclusão

O padrão Adapter é bastante comum no mundo do C# e é bastante usado quando temos que adaptar algumas classes existentes para uma nova interface. Pode aumentar a complexidade do código essas classes adicionais (adaptadoras), mas vale a pena o esforço com certeza.

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay