El patrón de diseño Adapter te sirve cuando tienes interfaces diferentes o incompatibles entre sí y necesitas que el cliente pueda usar ambas del mismo modo.
El patrón de diseño Adapter dice en su definición que convierte una interfaz o clase en otra interfaz que el cliente necesita.
Cuales son las partes del patrón de diseño Adapter
Las partes de patrón Adapter son
- Target: la interfaz que usamos para crear el adapter.
- Adapter: es la implementación del target y que se ocupará de realizar la adaptación.
- Client: es el que interactúa y usa el adapter.
- Adaptee: es la interfaz incompatible que necesitamos adaptar con el adapter.
Como se crea el patrón de diseño Adapter en Java
Mencionamos antes que el patrón tenía varias partes. Un cliente que interactúa con el Adapter para conseguir lo que necesita. El Target de la cual se implementar el Adapter, quien será el encargado de adaptar la respuesta del Adaptee para que el Client la entienda. El Adaptee que representa la clase con una interfaz incompatible para el cliente
Llevemos esto a un ejemplo en el cual un Cliente necesita información de un servicio BankService que devuelve la información en la clase BankData.
- Client: el cliente necesita información de una cuenta bancaria y la necesita en la clase User.
- Client: el cliente llama al adapter para conseguir información del User
- Adapter: el adapter llama al servicio para que devuelva información.
- Adaptee: el servicio devuelve el BankUser, el Adaptee.
- Adapter: el adapter convierte BankData en User y la devuelve al client.
- Client: el cliente recibe la info en User. La clase que si entiende.
El servicio que devuelve BankData
package patterns.adapter;
public class BankService {
public BankData findByAccountNumber(int accountNumber) {
if (accountNumber == 1) {
return new BankData(accountNumber,"Nick", 100d);
} else if (accountNumber == 3) {
return new BankData(accountNumber,"Susan", 200d);
} else {
return null;
}
}
}
La clase BankData con la info
package patterns.adapter;
public class BankData {
private int account;
private String name;
private double balance;
public BankData(int account, String name, double balance) {
this.account = account;
this.name = name;
this.balance = balance;
}
public String getName() {
return name;
}
public int getAccount() {
return account;
}
public double getBalance() {
return balance;
}
}
La clase User que requiere el cliente
package patterns.adapter;
public class User {
private int id;
private String name;
private double totalAvailable;
public User(int id, String name, double totalAvailable) {
this.id = id;
this.name = name;
this.totalAvailable = totalAvailable;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getTotalAvailable() {
return totalAvailable;
}
}
El target (interfaz) de la cual creamos el Adapter
package patterns.adapter;
public interface UserAdapter {
User getUser(int accountNumber);
}
La implementación del adapter
package patterns.adapter;
public class UserAdapterImpl implements UserAdapter {
private BankService service = new BankService();
@Override
public User getUser(int accountNumber) {
BankData bankData = service.findByAccountNumber(accountNumber);
User user = new User(bankData.getAccount(), bankData.getName(), bankData.getBalance());
return user;
}
}
El client que necesita información en la clase User
package patterns.adapter;
public class Client {
public static void main(String[] args) {
UserAdapterImpl adapter = new UserAdapterImpl();
adapter.getUser(1);
}
}
Conclusión
Hemos visto que el patrón Adapter resuelve incompatibilidades entre interfaces adaptando una interfaz hacia la otra utilizando un adapter encargado de la conversión entre interfaces.
Se trata de un patrón muy utilizado sobre todo cuando nos comunicamos con apis externas y necesitamos adaptar su respuesta hacia nuestras interfaces.
Puedes descargar este código en github