Lo primero será como muestran las buenas prácticas el gráfico UML.
Del cual hemos de memorizar los nombres para poder señalar con mayor facilidad cada uno de los elementos de cada implementación concreta. Implementor, ConcreteImplementor, Abstraction y RefinedAbstraction.
Buscando implementaciones del patrón me encuentro esta:
http://javapapers.com/design-patterns/bridge-design-pattern/
que pasado a UML a través de https://app.genmymodel.com/genmymodel queda en :
todo esto se ha hecho para evitar la siguiente composición.
Que tiene dos defectos que soluciona el patron Bridge. El primero es que cada subclase depende directamente, hereda, de un padre de modo que cada vez que quiera cambiar algo de este sus hijos se veran afectados. Llámesele acoplamiento. A la izquierda si cambio algo de Bike o de Car, sus respectivos produceX y assembleX se verán afectados. Véase, sin embargo, como con el diseño de la parte superior la vinculación del produce o assemble solo es efectiva en tanto que:
manufacture(){
manufacture1.work();
manufacture2.work();
}.
Y por tanto un cambio en Bike o en Car no tendrá ninguna consecuencia en produce o assemble.
Sigamos con otro ejemplo. Este de http://www.oodesign.com/bridge-pattern.html
Este grafico yo lo pintaria así:
Y vemos ciertas diferencias. La más evidente es que CustomerOps o GlobalMarketOps realizan, implementan un interfaz y de este modo no se obliga en tiempo de compilación a escribir un constructor con un argumento del tipo IPersistenceData. Ya eque el interfaz no puede tener nunca un constructor. Y el otro lado de lo mismo es que el interfaz no puede tener ninguna variable instanciable. Asi lo que se pasaba por el constructor de la clase abstracta Vehicle para asignarlo a las instancias de workshop no tiene cabida en este segundo ejemplo. Esto obliga al cliente a gestionar tanto el constructor como sus asignaciones y por tanto es trabajo repetido y que da lugar a errores.
Lo mismo pasa con los
Otra diferencia es que los distintos XData no se acumulan es sus clientes RefinedAbstraction , es decir, se usa uno u otro. No así en el primer ejemplo en el que los diferentes ConcreteImplementor se usaban ambos en el manufacture de sus RefinedAbstraction. No se hace uso en el caso de la persistencia del trabajo acumulativo de cada uno de los.
Por ahora está mucho más exprimido el patrón en el primer ejemplo que en el segundo. También mejor implementado. El abstraction en la persistencia es un interfaz y no debería.
Vayamos a por otro:
Este en http://www.programcreek.com/2011/10/java-design-pattern-bridge/
Este ejemplo me aclara algo. Y es que pone de manifiesto que es la instanciación de RedefinedAbstraction donde se elige el tipo ConcreteImplementor
public class Main { public static void main(String[] args){ ITV tv = new SonyTV(); LogitechRemoteControl lrc = new LogitechRemoteControl(tv); lrc.setChannelKeyboard(100); } }
el diagrama estaria mejor asi: