O Adapter é um padrão estrutural que permite que objetos com interfaces incompatíveis colaborem entre si. O Adapter atua como um wrapper entre dois objetos, capturando chamadas para um objeto e as transformando em um formato que o segundo objeto possa entender.
- Quando você quer usar uma classe existente, mas sua interface não corresponde à interface que você precisa
- Quando você precisa reutilizar várias subclasses existentes que não possuem alguma funcionalidade comum que não pode ser adicionada à superclasse
- Para fazer classes com interfaces incompatíveis trabalharem juntas
- Quando você precisa integrar bibliotecas ou sistemas legados com código novo
from abc import ABC, abstractmethod
# Interface alvo que o cliente espera usar
class AnaliseTexto(ABC):
@abstractmethod
def processar_texto(self, texto: str) -> dict:
pass
# Classe existente (incompatível)
class AnalisadorLegado:
def extrair_palavras(self, texto: str) -> list:
return texto.lower().split()
def contar_frequencia(self, palavras: list) -> dict:
frequencia = {}
for palavra in palavras:
frequencia[palavra] = frequencia.get(palavra, 0) + 1
return frequencia
# Adapter
class AnalisadorAdapter(AnaliseTexto):
def __init__(self, analisador: AnalisadorLegado):
self.analisador = analisador
def processar_texto(self, texto: str) -> dict:
palavras = self.analisador.extrair_palavras(texto)
return self.analisador.contar_frequencia(palavras)
# Cliente
class Aplicacao:
def __init__(self, analisador: AnaliseTexto):
self.analisador = analisador
def analisar_documento(self, texto: str):
resultado = self.analisador.processar_texto(texto)
return resultado
# Exemplo de uso
def main():
# Sistema legado
analisador_legado = AnalisadorLegado()
# Criando adapter
adapter = AnalisadorAdapter(analisador_legado)
# Cliente usando o adapter
app = Aplicacao(adapter)
# Testando
texto = "Olá mundo! Olá Python! Python é incrível!"
resultado = app.analisar_documento(texto)
print("Frequência de palavras:")
for palavra, frequencia in resultado.items():
print(f"{palavra}: {frequencia}")
if __name__ == "__main__":
main()- Princípio de Responsabilidade Única: separa a interface ou conversão de dados da lógica de negócios
- Princípio Aberto/Fechado: permite introduzir novos adaptadores sem quebrar o código existente
- Reutilização de código: permite usar classes existentes mesmo com interfaces incompatíveis
- Flexibilidade: permite que classes com interfaces incompatíveis trabalhem juntas
- Aumenta a complexidade geral do código por introduzir novas interfaces e classes
- Às vezes é mais simples mudar a classe de serviço para corresponder ao resto do código
- Pode adicionar várias camadas de adaptação, tornando o código mais difícil de entender
- Considere usar o padrão quando você quer usar uma classe existente mas sua interface não corresponde à que você precisa
- Decida entre usar herança (adapter de classe) ou composição (adapter de objeto)
- Mantenha o adapter o mais simples possível, focando apenas na tradução de interfaces
- Se precisar de adaptação bidirecional, considere criar adaptadores separados para cada direção
- Use quando precisar reutilizar várias subclasses existentes que não têm alguma funcionalidade comum