Bridge (padrón de deseño)

O padrón **Ponte**, tamén coñecido como Bridge, é un padrón, pertencente á categoría de padróns estruturais, empregado na enxeñaría do software. Con el pretendese separar unha abstracción da súa implementación, desta forma poderanse empregar implementacións alternativas.

O padrón Ponte pode ser moi útil cando as implementacións varian a miúdo. Nese caso, as características da programación orientada a obxectos, tórnanse moi útiles, podendo facer cambios no código cun mínimo coñecemento previo do programa.

## Obxectivos 
* Desacoplar unha abstracción da súa implementación de forma que ambas poidan variar independentemente.
* Illamento mais aló da encapsulación.

## Aplicabilidade 
Podemos empregar o padrón Ponte cando:
* Queremos evitar unha ligazón permanente entre a abstracción e a súa implementación, podendo ser debido a que a implementación debe ser seleccionada ou cambiada en tempo de execución.
* Tanto as abstracción coma as súas implementación deben ser extensibles por medio de subclases. Neste caso, o padrón Ponte permite combinar abstracción e implementación diferentes e estendelas independentemente.
* Os cambios na implementación dunha abstracción non deben impactar nos clientes,o seu código non ten que ser recompilado.
* Queremos ocultar a implementación dunha abstracción completamente ós clientes.
* Deséxase compartir unha implementación entre múltiples obxectos, e isto é ocultado ós clientes.

## Participantes 
* **Abstracción** (Abstraction): define a clase interface. Mantén unha referencia ó obxecto implementador.
* **Abstracción refinada** (RefinedAbstraction): estende e implementa a interface Abtracción.
* **Implementador** (Implementor): define a interface para as clases implementación. Esta interface non ten que corresponderse exactamente coa interface de Abstraction, as das interfaces poden ser bastante diferentes. Tipicamente a interface Implementor prové só de operacións primitivas, e Abstraction define operacións de alto nivel baseadas nestas primitivas.
* **Implementador Concreto** (ConcreteImplementor): as clases implementadas

## Consecuencias 
* Desacoplamento do obxecto interface e implementación: unha implementación non é limitada permanentemente a unha interface. A implementación dunha abstracción pode configurarse en tempo de execución. Ademais, un obxecto, ten a posibilidade de cambiar a súa implementación en tempo de execución. Desacopla Abstraction e Implementor tamén elimina as dependencias sobre a implementación en tempo de compilación. Cambiar unha clase de implementación non require recompilar a clase Abstraction nin os seus clientes. Esta propiedade é esencial cando hai que asegurar a compatibilidade binaria entre diferentes versións dunha biblioteca de clases, fomentando as capas, que nos leven a un nivel mellor estruturado.
* Mellorar a estensibilidade: Pódese estender as xerarquías de abstracción e implementación de forma independente.

## Estrutura 
O cliente non quere lidiar cos detalles dependentes da plataforma. O padrón Ponte encapsula estas complexidades tras unha capa abstracta.

Ponte enfatiza identificar e desacoplar a abstracción de interface da abstracción da implementación.
px 500|centro

## Implementación 
* Só un Implementador: en situación onde existe só unha implementación, non é preciso crear una clase Implementor abstracta, sendo este, un caso especial do padrón no que hai unha relación un-a-un entre Abstraction e Implementor. Non obstante, esta separación é moi útil cando un cambio na implementación dunha clase non debe afectar os seus clientes.
* Implemementador: Sendo esta unha das principais diferenzas có padrón estratexia, se a abstracción coñece a xerarquía de implementadores pode crear o implementador no construtor, podendo decidir cal instanciar dependendo dos parámetros do construtor. O inconveniente ven dado pola dependencia da xerarquía, se aparece un novo teremos que modificar a abstracción.

Outra aproximación é delegar noutro obxecto (singleton), este encargarase de proporciona o implementador concreto da abstracción.

* Compartir implementadores.
* Empregando herdanza múltiple.

## Ponte con outros padróns 
* Adaptador fai que as cousas funcionen despois de ser deseñadas, Ponte fai que as cousas funcionen antes de ser deseñadas.
* Ponte é deseñado para permitir que a abstracción e a implementación varíen de forma independente.Adaptador é deseñado para que clases non relacionadas traballen xuntas.
* Estado, Estratexia, Ponte (e algúns casos de Adaptador) teñen solucións estruturais semellantes. Diferéncianse na intención, resolven diferentes problemas.A estrutura de Estado e de Ponte é idéntica (excepto que Ponte admite xerarquías de herdanza envolventes, mentres que Estado só permite unha). Os dous padróns usan a mesma estrutura para resolver diferentes problemas: Estado permite cambiar o comportamento dun obxecto o cambiar o seu estado, mentres que Ponte pretende desacoplar a abstracción da súa implementación, podendo variar estas dúas de forma independente.
* Se a clase interface delega a creación a clase implementación, entón o deseño usualmente emprega o padrón Fábrica Abstracta para crear os obxectos implementación.
* Ponte semella o padrón adaptador , pero mentres que o padrón Adaptador intenta que as interfaces dunha ou máis clases sexa a mesma que para unha clase particular, Ponte está deseñado para separar as clases interfaces da súa implementación, desta forma poder variar e substituír as súas implementacions sen cambiar o código cliente.

## Exemplo 
```java
/*
 * Memoria que permite o intercambio dos datos almacenados na mesma
 * 
 */

class MemoriaIntercambio extends Memoria{
	
  public MemoriaIntercambio(ImplementacionMemoria memoria){
    super(memoria);
  }

  // Intercambia o dato almacenado na posición i, co almacenado na posición j
  public void intercambiar(Integer i, Integer j){
    String aux = super.obtener(i);
    super.guardar(i, super.obtener(j));
    super.guardar(j, aux);

  }
}
```

```java
/*
 * Memoria que unicamente permite obter e gardar datos.
 * 
 */

class Memoria {
	
  public Memoria(ImplementacionMemoria memoria){
    _imp = memoria;
  }

  //Obtén o dato da posición i
  public String obtener(Integer i) { 
    return _imp.obtener(i);
  }

  // Garda o dato na posición i
  public void guardar(Integer i, String dato){ 
    _imp.guardar(i, dato);
  }

  // atributo privado coa implementación específica da memoria
  private ImplementacionMemoria _imp;
}
```

```java
/**
 * Clase Main do exemplo do padrón Ponte (Bridge)
 *
 */
public class main {

	/**
	 * @param args
	 */
	static public void main(String argv[]) {
		
		ImplementacionMemoria mhash = new ImplementacionHash();
		ImplementacionMemoria mvector = new ImplementacionVector();
		
		Memoria m = new Memoria(mhash);
		MemoriaIntercambio mi = new MemoriaIntercambio(mvector);
		
		m.guardar(0, "0xfa21");
		m.guardar(1, "0x8732");
		m.guardar(2, "0x329f");
		
		mi.guardar(0, "0xfa21");
		mi.guardar(1, "0x8732");
		mi.intercambiar(0, 1);
		
		System.out.println(m.obtener(1));
		
		System.out.println(mi.obtener(0));
	}

}
```

```java
/*
 * Implementación de Memoria usando Vector.
 * 
 */

import java.util.Vector;

class ImplementacionVector implements ImplementacionMemoria {

  public ImplementacionVector() {
    _mem = new Vector();
  }
  //Obtén o dato da posición i
  public String obtener(Integer i) {
    return _mem.get(i.intValue());
  }

  // Garda o dato na posición i
  public void guardar(Integer i, String dato) {
	if (_mem.size()  _mem;
}
```

```java
/*
 * Interface que debe de ser implementada, polas implementacións específicas da memoria
 * 
 */

interface ImplementacionMemoria {

  //Obtén o dato da posición i
  public String obtener(Integer i);

  // Guarda el dato en la posición i
  public void guardar(Integer i, String dato);

}
```

```java
/*
 * Implementación de Memoria usando HashMap.
 * 
 */

import java.util.HashMap;

class ImplementacionHash implements ImplementacionMemoria {

  public ImplementacionHash() {
    _mem = new HashMap();
  }
  //Obtén o dato da posición i
  public String obtener(Integer i) {
    return _mem.get(i);
  }

  // Garda o dato na posición i
  public void guardar(Integer i, String dato) { 
    _mem.put(i, dato);
  }

  private HashMap _mem;
}
```