Everton Andrade
Posted on October 4, 2020
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; }
}
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 }
};
}
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;
}
}
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
:
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);
}
}
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();
}
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();
}
}
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();
}
}
Assim que iniciarmos nosso aplicativo, veremos o seguinte resultado:
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.
Posted on October 4, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.