Tuesday, April 4, 2017

Adapter Design Pattern

Em engenharia de software, o padrão de projeto Adapter permite que você trabalhe com novas implementações sem modificar o código já existente. Por exemplo, se um framework utilizado pelo sistema é atualizado e algumas interfaces são alteradas nessa nova versão, você pode utilizar o padrão Adapter para permitir que o sistema acesse as novas funcionalidades sem alterar o código existente.

Resumidamente o padrão Adapter permite que duas interfaces incompatíveis, mas com funcionalidades semelhantes, trabalhem juntas.

O padrão Adapter é fácil de entender porque o mundo real está repleto de dele!

Exemplo

Suponha que você tenha uma ChaveA que abre uma FechaduraA. Conceitualmente a fechadura é a interface que exige uma determinada chave para que a porta seja aberta:


O código em java do diagrama anterior:
public class ChaveA {
    //atributos e métodos
}
public interface FechaduraA {

    void open(ChaveA chaveA);
}
public class FechaduraAImpl implements FechaduraA{

    @Override
    public void open(ChaveA chaveA) {
        System.out.println("Fechadura A aberta!");
    }   
}
E a classe cliente que contém o método main():
public class Cliente {

    public static void main(String[] args) {

        FechaduraA fechaduraA = new FechaduraAImpl();
        ChaveA chaveA = new ChaveA();
        open(fechaduraA, chaveA);
    }
    //requer como parâmetro uma FechaduraA e uma ChaveA para abrir
    static void abrir(FechaduraA fechaduraA, ChaveA chaveA){

        fechaduraA.open(chaveA);
    }   
}
Chamando o método main() na classe Cliente conseguimos abrir a fechadura sem problema. A saída é como segue:
Fechadura A aberta!
O método estático abrir() na classe Cliente exige dois argumentos, um objeto Fechadura e outro objeto do tipo Chave para então invocar o método open() da fechadura.

Imagine que apareça no mercado um novo padrão de fechaduras, o qual requeira também um novo tipo de chave.
public interface NovoPadraoFechaduraA {

    void open(ChaveB chaveB);
}
public class ChaveB {
    //código da classe B
}
E uma implementação concreta da interface NovoPadrãoFechaduraA:
public class NovoPadraoFechaduraAImpl implements NovoPadraoFechaduraA{

    @Override
    public void open(ChaveB chaveB) {
        System.out.println("Novo Padrão Fechadura A aberta!");
    }   
}

Seu sistema precisa implementar esse novo padrão, porém outras partes da aplicação continurão a usar o modelo antigo. Assim surge a questão: como atender a nova demanda sem prejudicar as outras partes que utilizam o padrão antigo? Em outras palavras, você precisa implementar o novo padrão, mas não poderá modificar o método estático abrir() da classe Cliente, o qual exige os modelos antigos de fechadura e chave!

O padrão Adapter resolve de forma eficiente essa questão. Ele torna possível utilizar as novas interfaces sem alterar o método abrir(). Para isso apenas precisamos criar uma classe que implemente a interface FechaduraA e também utilize as funcionalidades da interface da interface NovoPadraoFechaduraA. Chamemos esta classe de ChaveAAdaptador:

Código da classe Adapter:
public class ChaveAAdaptador implements FechaduraA{

    NovoPadraoFechaduraA novoPadrao;
    ChaveB chaveB;

    public ChaveAAdaptador(NovoPadraoFechaduraA fechadura) {       

        this.novoPadrao = fechadura;
        this.chaveB = new ChaveB();
    }   
    @Override
    public void open(ChaveA chaveA) {

        this.novoPadrao.open(chaveB);       
    }       
}
Instanciamos o adaptador na classe Cliente e podemos usar o novo padrão sem alterar o método abrir():
public class Cliente {
 
    public static void main(String[] args) {
        //modelo antigo
        FechaduraA fechaduraA = new FechaduraAImpl();
        ChaveA chaveA = new ChaveA();
        abrir(fechaduraA, chaveA);     
        //novo padrão
        NovoPadraoFechaduraA novoPadraoFechaduraA = new NovoPadraoFechaduraAImpl();
        ChaveAAdaptador adaptador = new ChaveAAdaptador(novoPadraoFechaduraA);
        abrir(adaptador, chaveA);
    }
  
    static void abrir(FechaduraA fechaduraA, ChaveA chaveA){

        fechaduraA.open(chaveA);
    }   
}
saída
Fechadura A aberta!
Novo Padrão Fechadura A aberta!

No comments:

Post a Comment