Padrão Adapter
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 71 de 87.
O padrão Adapter é um padrão de projeto estrutural que permite que interfaces incompatíveis trabalhem juntas. Ele atua como uma ponte entre duas classes, convertendo a interface de uma classe em uma interface que o cliente espera. Pense nele como um adaptador de energia que permite conectar um dispositivo europeu a uma tomada americana.
Imagine que você tenha uma interface MediaPlayer existente que reproduz arquivos de áudio, mas precise integrar uma biblioteca de terceiros que usa uma interface completamente diferente para reproduzir vídeos:
// Interface existente que seu código usa
interface MediaPlayer {
void play(String filename);
}
// Classe de terceiros com interface incompatível
class AdvancedVideoPlayer {
public void playVideo(String filename) {
System.out.println("Playing video: " + filename);
}
}O adaptador envolve a classe incompatível e implementa a interface esperada, traduzindo as chamadas entre elas:
class VideoPlayerAdapter implements MediaPlayer {
private AdvancedVideoPlayer videoPlayer;
public VideoPlayerAdapter() {
this.videoPlayer = new AdvancedVideoPlayer();
}
public void play(String filename) {
videoPlayer.playVideo(filename);
}
}Agora seu código cliente pode usar o reprodutor de vídeo por meio da conhecida interface MediaPlayer:
MediaPlayer player = new VideoPlayerAdapter();
player.play("movie.mp4"); // Saída: Reproduzindo vídeo: movie.mp4O Padrão Adapter é inestimável ao integrar código legado ou bibliotecas de terceiros sem modificar o código-fonte delas. O cliente permanece sem saber que está trabalhando com uma classe adaptada. Ele simplesmente usa a interface que conhece.
Desafio
FácilVamos construir um sistema de conversão de temperatura usando o padrão Adapter! Você tem um aplicativo de previsão do tempo existente que trabalha com temperaturas em Celsius, mas precisa integrar um sensor de temperatura legado que fornece leituras apenas em Fahrenheit. Em vez de modificar qualquer um dos sistemas, você criará um adaptador que conecta os dois.
Você organizará seu código em quatro arquivos:
TemperatureProvider.java: Defina a interface que seu aplicativo de previsão do tempo espera. Ela deve declarar um métodogetTemperatureCelsius()que retorna um double representando a temperatura em Celsius.FahrenheitSensor.java: Isso representa o sensor legado com uma interface incompatível. Crie uma classe com um campo double privado para a temperatura em Fahrenheit, definido por meio do construtor. Ela deve ter um métodoreadFahrenheit()que retorna o valor armazenado em Fahrenheit.SensorAdapter.java: Crie o adaptador que torna o sensor Fahrenheit compatível com seu aplicativo de previsão do tempo. Seu adaptador deve implementarTemperatureProvidere encapsular umFahrenheitSensor. QuandogetTemperatureCelsius()for chamado, ele deve ler o valor do sensor e convertê-lo para Celsius usando a fórmula:(fahrenheit - 32) * 5 / 9.Main.java: Reúna tudo! Você receberá uma entrada: uma leitura de temperatura em Fahrenheit (double).Crie um
FahrenheitSensorcom o valor de entrada. Em seguida, crie umSensorAdapterque encapsule esse sensor. Armazene o adaptador em uma variávelTemperatureProviderpara demonstrar que seu aplicativo de previsão do tempo pode usá-lo por meio da interface esperada.Imprima o resultado neste formato:
Temperature: [celsius] C, em que celsius é formatado com uma casa decimal.
Você receberá uma entrada: a temperatura em Fahrenheit (double).
Por exemplo, com a entrada 98.6, sua saída seria:
Temperature: 37.0 CObserve como sua classe Main trabalha inteiramente com a interface TemperatureProvider. Ela não sabe que a temperatura real vem de um sensor Fahrenheit adaptado nos bastidores. Essa é a elegância do padrão Adapter!
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double fahrenheit = scanner.nextDouble();
// TODO: Crie um FahrenheitSensor com o valor de entrada
// TODO: Crie um SensorAdapter que envolve o sensor
// TODO: Armazene o adapter em uma variável TemperatureProvider
// TODO: Obtenha a temperatura em Celsius e imprima-a
// Formato: "Temperature: [celsius] C" com uma casa decimal
// Dica: Use String.format("%.1f", value) para formatação
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online