Adapter (patrón de deseño)

Na Galipedia, a Wikipedia en galego.

Adapter (tamén chamado wrapper ou adaptador) e un patrón de deseño estrutural que serve para transformar unha interface noutra compatible coa clase na que se quere utilizar.[1]

Motivación[editar | editar a fonte]

Algunhas veces unha clase deseñada para ser reusada non pode selo por que a súa interface non coincide coa interface específica que require unha determinada aplicación. Un adaptador permite as clases traballar conxuntamente con normalidade. O adaptador traduce as chamadas a súa interface en chamadas o interface orixinal, e a cantidade de código necesario para facelo é habitualmente pequeno. O adaptador é tamén responsable de transformar as chamadas. Un exemplo disto sería que unha clase proporcionase valores booleanos na forma de cadeas “true” ou ”false” pero a clase dende a que se vai utilizar necesite eses valores en formato 1 e 0, desta forma a clase adaptadora realizaría o cambio.

Aplicabilidade[editar | editar a fonte]

  1. Utilizarase este patrón cando se queira usar una clase existente pero a interface non coincida coa que se necesita.
  2. Cando se queira crear unha clase reusable por clases non relacionadas ou imprevistas e que non teñen por que ter a mesma interface.
  3. Cando queiramos utilizar subclases existentes pero non sexa axeitado adaptar as súas interfaces. En este caso pódese adaptar a súa interface por medio dunha clase adaptadora da interface do seu pai.

Estrutura[editar | editar a fonte]

Temos dúas posibles opcións a hora de abordar este patrón:

Opción 1.
Diagrama secuencia Opción 1.
Diagrama obxectos Opción 1.
  • Utilizar a herdanza múltiple, de forma que a clase adaptadora herde de ambas interfaces.
Opción 2.
Diagrama secuencia Opción 2.
Diagrama obxectos Opción 2.
  • Substituír a herdanza múltiple por herdanza a clase obxectivo e unha referencia a clase adaptada.

Participantes[editar | editar a fonte]

  • Obxectivo: Define a interface específica que o cliente utiliza.
  • Cliente: Colabora cos obxectos que conforman o obxectivo.
  • Adaptado: Define unha interface existente que necesita ser adaptada.
  • Adaptador: Adapta a interface existente a interface do obxectivo.

Consecuencias[editar | editar a fonte]

  • Clase Adaptadora
  1. So permite adaptar unha clase concreta, non permite adaptar unha clases e todas as súas subclases.
  2. Permite que o Adaptador redefina o comportamento do Adaptado, por ser unha subclase de Adaptable.
  3. Introduce un so obxecto, e non se necesita ningún punteiro de indirecion adicional para obter o obxecto adaptado.
  • Obxecto Adaptador
  1. Permite que un único Adaptador funcione con moitos Adaptados (co o Adaptado e todas as súas subclases). O Adaptador tamén pode engadir funcionalidade a todos os Adaptados a vez.
  2. Fai que sexa máis difícil redefinir o comportamento de Adaptado. Se necesitara crear unha subclase Adaptado e facer que o Adaptador se refira a subclase en vez de a clase Adaptado.
  3. O obxecto adaptador introduce un obxecto adicional, polo que a eficiencia da solución pode resentirse

Código exemplo[editar | editar a fonte]

  • Clase Adaptadora
public class Adaptado 
{
	public void peticionEspecifica()
	{
		System.out.println("Peticion especifica Herdanza Multiple...");
	}
}
 
public interface Obxetivo 
{
	public void peticion();
}
 
public class Adaptador extends Adaptado implements Obxetivo 
{
	public void peticion() 
	{
		peticionEspecifica();
	}
}
 
public class Cliente 
{
	public static void main (String[] arg)
	{
		Obxetivo Adr = new Adaptador();
		Adr.peticion();
	}
}
  • Obxecto Adaptador
public class Adaptado 
{
	public void peticionEspecifica()
	{
		System.out.println("Peticion especifica Composicion...");
	}
}
 
public interface Obxetivo 
{
	public void peticion();
}
 
public class Adaptador implements Obxetivo
{
	private Adaptado _adaptado;
 
	public Adaptador (Adaptado a)
	{
		_adaptado = a;
	}
 
	public void peticion() 
	{
		_adaptado.peticionEspecifica();
	}
}
 
public class Cliente 
{
	public static void main (String[] arg)
	{
		Adaptado Ado = new Adaptado();
		Obxetivo Adr = new Adaptador(Ado);
		Adr.peticion();
	}
}

Exemplo[editar | editar a fonte]

Exemplo de uso.

No seguinte exemplo queremos que unha clase cliente sexa capaz de comprobar o estado dunha rede de auga e de electricidade nun determinado punto.

Para a enquisa da electricidade dispoñemos dun método ao que poderíamos chamar directamente dende a comprobación da electricidade. No caso da agua so dispoñemos dun método getNivel, que nos da o nivel de auga nese momento. Deberemos comprobar nós se o nivel é o adecuado para determinar que a comprobación é certa.

É neste punto onde se introduce o patrón adaptador, para permitir a comprobación en base aos valores proporcionados pola outra clase.

Notas[editar | editar a fonte]

  1. Freeman, Eric; Freeman, Elisabeth; Kathy, Sierra; Bates, Bert (2004) (paperback). Head First Design Patterns. O'Reilly Media. pp. 244. ISBN 978-0-596-00712-6. OCLC 809772256. http://www.headfirstlabs.com/books/hfdp/. Consultado o 30 de abril de 2013. 

Véxase tamén[editar | editar a fonte]

Outros artigos[editar | editar a fonte]