Padrão Adapter

A utilização de frameworks e biblioteca de terceiros é muito comum durante o desenvolvimento de qualquer software, devido a comodidade e facilidade de utilização.

Problema

Vamos considerar o seguinte exemplo: é preciso fazer um sistema que manipule imagens, para isto será utilizado uma biblioteca que oferece essas funcionalidades. Suponhamos que será necessário ter um método para carregar a imagem de um arquivo e outro para exibir a imagem na tela. Para fins didáticos, considere o exemplo abaixo

public class ManipuladorImagemBibliotecaA {

    public void carregarImagem(String arquivo) {
        System.out.println("Imagem " + arquivo + " carregada.");
    }
 
    public void desenharImagem(int posicaoX, int posicaoY) {
        System.out.println("Image desenhada");
    }

}

Porém, existem outras alternativas de bibliotecas que oferecem a mesma funcionalidade, porém com nomes de métodos diferentes.

public class ManipuladorImagemBibliotecaB {

    public void carregarDados(String arquivo) {
        System.out.println("Imagem " + arquivo + " carregada.");
    }
 
    public void exibirImagem(int largura, int altura, int posicaoX,
            int posicaoY) {
        System.out.println("Imagem exibida");
    }

}

Independente da biblioteca que escolhermos, teremos um cenário onde nosso sistema depende da biblioteca, uma vez que realizamos chamadas de métodos para essa biblioteca.

Como podemos então construir o sistema de maneira que ele fique independente de qual biblioteca será utilizada? De maneira que, caso seja decidido mudar a biblioteca por outra no futuro, nosso sistema não seja afetado?

Solução

O Adapter atua como um "wrapper", envolvendo dois objetos. Sua intenção é:

"Converter a interface de uma classe em outra interface, esperada pelo cliente. O Adapter permite que interfaces incompatíveis trabalhem em conjunto – o que, de outra forma, seria impossível."

Ou seja, dado um conjunto de classes com mesma responsabilidade, mas interfaces diferentes, utilizamos o Adapter para unificar o acesso a qualquer uma delas. Precisamos então, inicialmente, fornecer uma interface comum para o cliente, oferencendo o comportamento que ele necessita

public interface ManipuladorImagem {

    public void carregarImagem(String arquivo);
    public void desenharImagem(int largura, int altura, 
        int posicaoX, int posicaoY);

}

Dessa maneira, toda vez que precisarmos utilizar um manipulador de imagem, iremos usar apenas objetos dessa interface. Essas implementações, por sua vez, estendem ou usam objetos do Manipulador A ou B, delegando e adaptando as chamadas.

public class ManipuladorImagemA extends ManipuladorImagemBibliotecaA 
    implements ManipuladorImagem {

    public void carregarImagem(String arquivo) {
        super.carregarImagem(arquivo);
    }
    
    public void desenharImagem(int largura, int altura, 
        int posicaoX, int posicaoY) {
        super.desenharImagem(posicaoX, posicaoY);
    }

}

De posse dos adaptadores, nosso cliente fica então independente de qual biblioteca será utilizada, utilizando apenas a interface comum definida no início.

public static void main(String[] args) {
    ManipuladorImagem imagem = new ManipuladorImagemA();
    imagem.carregarImagem("teste.png");
    imagem.desenharImagem(0, 0, 10, 10);
 
    imagem = new ManipuladorImagemB();
    imagem.carregarImagem("teste.png");
    imagem.desenharImagem(0, 0, 10, 10);
}

Last updated

Was this helpful?