Resumo : neste tutorial, você aprenderá como usar o padrão C# Adapter para permitir que classes de interfaces incompatíveis trabalhem juntas.
Introdução ao padrão C# Adapter
O padrão Adapter converte uma interface em outra interface que os clientes esperam. O padrão Adapter permite que classes de interfaces incompatíveis trabalhem juntas.
Suponha que você esteja viajando para um país estrangeiro e queira carregar seu telefone. O problema é que a tomada elétrica naquele país tem um formato diferente do plugue do carregador do seu telefone.
Para resolver esse problema, você pode usar um adaptador que converte a tomada externa no formato de plugue do carregador do telefone.
Este adaptador serve como um invólucro que traduz a interface do soquete externo na interface que o carregador do seu telefone espera. Ao fazer isso, você pode carregar seu telefone sem alterar a tomada externa.
Da mesma forma, o padrão Adapter cria um adaptador que converte a interface de um objeto em uma interface que os clientes esperam, permitindo que trabalhem juntos sem modificar seu código.
O padrão Adapter possui duas variantes: adaptador de objeto e adaptador de classe.
Adaptador de objeto
O diagrama UML a seguir ilustra o adaptador de objeto:
Neste diagrama UML do adaptador de objeto:
ITarget
interface: Esta é a interface com a qual o cliente espera trabalhar. É também a interface que aAdapter
classe implementará.Adaptee
: é a classe que possui uma interface que não é compatível com aITarget
interface. É a classe que aAdapter
classe irá embrulhar e adaptar.Adapter
: é a classe que implementa a interface de destino e envolve oAdaptee
objeto. AAdapter
classe é responsável por traduzir as chamadas daITarget
interface para aAdaptee
interface do e delegar o trabalho a ela.
Neste padrão, o Adapter
possui um membro que é o Adaptee
objeto. O Operation()
método da Adapter
classe chama o SpecificOperation()
método do Adaptee
objeto.
Exemplo de adaptador de objeto
Suponha que você precise implementar um recurso de pagamento em seu aplicativo de sistema. E você precisa usar uma classe de terceiros chamada PaymentProcessor
.
A PaymentProcessor
classe possui um método chamado ProcessPayment
, que aceita um decimal
argumento que representa o valor do pagamento:
public class PaymentProcessor
{
public void ProcessPayment(decimal amount)
{
Console.WriteLine($"You have paid {amount:C}.");
}
}
Linguagem de código: C# ( cs )
Mas seu aplicativo usa uma interface chamada IPaymentProvider
com um método
. O problema é que o MakePayment
método aceita dois argumentos: uma string que representa os detalhes do pagamento e um valor decimal que representa o valor do pagamento:MakePayment
public interface IPaymentProvider
{
void MakePayment(string details, decimal amount);
}
Linguagem de código: C# ( cs )
Como você pode ver, a interface que seu aplicativo espera é IPaymentProvider
incompatível com a classe PaymentProcessor
.
Para resolver esse problema, você pode aplicar o padrão Adaptador de objeto.
Para usar o PaymentProcessor
com sua IPaymentProvider
interface, você pode criar uma Adapter
classe chamada PaymentProviderAdapter
.
As PaymentProviderAdapter
necessidades de implementar a IPaymentProvider
interface e agrupar a
classe. Além disso, o PaymentProcessor
MakePayment
método precisa PaymnetProviderAdapter
traduzir a chamada para o ProcessPayment
método da
classe:PaymentProcessor
// The adapter class that adapts the PaymentProcessor
// to the IPaymentProvider interface
public class PaymentProviderAdapter : IPaymentProvider
{
private readonly PaymentProcessor _paymentProcessor;
public PaymentProviderAdapter(PaymentProcessor paymentProcessor)
{
_paymentProcessor = paymentProcessor;
}
public void MakePayment(string details, decimal amount)
{
Console.WriteLine($"Making a payment for: {details}");
_paymentProcessor.ProcessPayment(amount);
}
}
Linguagem de código: C# ( cs )
Agora, você pode usar a PaymentProcessor
classe em seu aplicativo da seguinte maneira:
public class Program
{
public static void Main(string[] args)
{
var paymentProcessor = new PaymentProcessor();
var paymentProvider = new PaymentProviderAdapter(paymentProcessor);
paymentProvider.MakePayment("C# design pattern course", 100.0m);
}
}
Linguagem de código: C# ( cs )
Na Program
aula:
- Primeiro, crie uma instância da
classe e crie uma instância daPaymentProcess
PaymentProviderAdapter
classe que envolve o
objeto ‘s.PaymentProcess
- Segundo, chame o método
MakePayment
da instância daPaymentProviderAdapter
classe para efetuar um pagamento, que por sua vez chamará oProcessPayment
método daPaymentProcessor
classe.
Junte tudo.
namespace ObjectAdapter;
// The third-party PaymentProcessor class
public class PaymentProcessor
{
public void ProcessPayment(decimal amount)
{
Console.WriteLine($"You have paid {amount:C}.");
}
}
// your application's IPaymentProvider interface
public interface IPaymentProvider
{
void MakePayment(string details, decimal amount);
}
// The adapter class that adapts the PaymentProcessor
// to the IPaymentProvider interface
public class PaymentProviderAdapter : IPaymentProvider
{
private readonly PaymentProcessor _paymentProcessor;
public PaymentProviderAdapter(PaymentProcessor paymentProcessor)
{
_paymentProcessor = paymentProcessor;
}
public void MakePayment(string details, decimal amount)
{
Console.WriteLine($"Making a payment for: {details}");
_paymentProcessor.ProcessPayment(amount);
}
}
public class Program
{
public static void Main(string[] args)
{
var paymentProcessor = new PaymentProcessor();
var paymentProvider = new PaymentProviderAdapter(paymentProcessor);
paymentProvider.MakePayment("C# design pattern course", 100.0m);
}
}
Linguagem de código: C# ( cs )
Saída:
Making a payment for: C# design pattern course
You have paid $100.00.
Linguagem de código: C# ( cs )
Padrão de adaptador de classe
O padrão Object Adapter usa composição para agrupar a classe incompatível. Enquanto isso, o padrão da classe Adapter usa herança .
No padrão Class Adapter, a Adapter
classe estende as Adaptee
classes e as classes de destino. A Adapter
classe então substitui o método da classe de destino e chama o método correspondente da Adaptee
interface.
C# não oferece suporte a múltiplas heranças que permitem que uma classe estenda duas ou mais classes. Porém, uma classe pode estender uma classe e implementar múltiplas interfaces.
O diagrama UML a seguir ilustra o padrão Class Adapter:
Neste diagrama, a Adapter
classe herda da Adaptee
classe em vez de compô-la. E o Operation()
método da Adapter
classe chama o SpecificOperation()
método da Adaptee
classe.
Exemplo de adaptador de classe
O exemplo a seguir é igual ao exemplo que usa o padrão de adaptador de objeto, mas usa o padrão de adaptador de classe:
namespace ClassAdapter;
// The third-party PaymentProcessor class
public class PaymentProcessor
{
public void ProcessPayment(decimal amount)
{
Console.WriteLine($"You have paid {amount:C}.");
}
}
// Our application's IPaymentProvider interface
public interface IPaymentProvider
{
void MakePayment(string details, decimal amount);
}
// The adapter class that adapts the PaymentProcessor to the IPaymentProvider interface
public class PaymentProviderAdapter : PaymentProcessor, IPaymentProvider
{
public void MakePayment(string details, decimal amount)
{
Console.WriteLine($"Making a payment for: {details}");
ProcessPayment(amount);
}
}
class Program
{
public static void Main(string[] args)
{
var paymentProvider = new PaymentProviderAdapter();
paymentProvider.MakePayment("C# design pattern course", 100.0m);
}
}
Linguagem de código: C# ( cs )
Resumo
- O padrão Adapter permite que objetos com interfaces incompatíveis trabalhem juntos.
- O padrão Object Adapter usa a composição enquanto a classe Class Adapter usa herança.