Mi opinión sobre el tema.
Los cuatro patrones tienen mucho en común, los cuatro a veces se denominan informalmente envoltorios o patrones de envoltorio. Todos usan la composición, ajustan el tema y delegan la ejecución al tema en algún momento, mapean una llamada de método a otra. Le ahorran al cliente la necesidad de tener que construir un objeto diferente y copiar todos los datos relevantes. Si se usan sabiamente, ahorran memoria y procesador.
Al promover un acoplamiento flexible, hacen que el código una vez estable esté menos expuesto a cambios inevitables y sea mejor legible para otros desarrolladores.
Adaptador
El adaptador adapta el sujeto (adaptado) a una interfaz diferente. De esta manera, podemos agregar objetos a una colección de tipos nominalmente diferentes.
El adaptador expone solo los métodos relevantes al cliente, puede restringir todos los demás, revelando intentos de uso para contextos particulares, como adaptar la biblioteca externa, hacer que parezca menos general y más centrado en las necesidades de nuestra aplicación. Los adaptadores aumentan la legibilidad y la autodescripción de nuestro código.
Los adaptadores protegen a un equipo del código volátil de otros equipos; una herramienta de salvamento cuando se trata de equipos offshore ;-)
El propósito menos mencionado es evitar que la clase de asignaturas exceda las anotaciones. Con tantos marcos basados en anotaciones, este uso se vuelve más importante que nunca.
El adaptador ayuda a evitar la limitación de Java de una sola herencia. Puede combinar varios adaptadores en un sobre dando la impresión de herencia múltiple.
Código sabio, el adaptador es "delgado". No debe agregar mucho código a la clase adaptee, además de simplemente llamar al método adaptee y las conversiones de datos ocasionales necesarias para realizar tales llamadas.
No hay muchos buenos ejemplos de adaptadores en JDK o bibliotecas básicas. Los desarrolladores de aplicaciones crean adaptadores para adaptar bibliotecas a interfaces específicas de aplicaciones.
Decorador
Decorator no solo delega, no solo asigna un método a otro, hacen más, modifican el comportamiento de algunos métodos de sujeto, puede decidir no llamar al método de sujeto en absoluto, delegar a un objeto diferente, un objeto auxiliar.
Los decoradores suelen agregar funcionalidad (transparente) al objeto envuelto, como el registro, el cifrado, el formateo o la compresión del sujeto. Esta nueva funcionalidad puede traer mucho código nuevo. Por lo tanto, los decoradores suelen ser mucho más "gordos" que los adaptadores.
El decorador debe ser una subclase de la interfaz del sujeto. Se pueden usar de forma transparente en lugar de sus sujetos. Vea BufferedOutputStream, todavía es OutputStream y puede usarse como tal. Esa es una gran diferencia técnica de los adaptadores.
Los ejemplos de libros de texto de toda la familia de decoradores se encuentran fácilmente en JDK: Java IO. Todas las clases como BufferedOutputStream , FilterOutputStream y ObjectOutputStream son decoradores de OutputStream . Pueden ser capas de cebolla, donde un decorador se decora nuevamente, agregando más funcionalidad.
Apoderado
El proxy no es un contenedor típico. Es posible que el objeto envuelto, el sujeto proxy, aún no exista en el momento de la creación del proxy. Proxy a menudo lo crea internamente. Puede ser un objeto pesado creado a pedido, o es un objeto remoto en una JVM diferente o un nodo de red diferente e incluso un objeto no Java, un componente en el código nativo. No tiene que envolver o delegar necesariamente a otro objeto en absoluto.
Los ejemplos más típicos son proxies remotos, inicializadores de objetos pesados y proxies de acceso.
Proxy remoto: el sujeto está en un servidor remoto, una JVM diferente o incluso un sistema que no es Java. Proxy traduce llamadas de método a llamadas RMI / REST / SOAP o lo que sea necesario, protegiendo al cliente de la exposición a la tecnología subyacente.
Proxy de carga diferida: inicialice completamente el objeto solo el primer uso o el primer uso intensivo.
Proxy de acceso: controla el acceso al sujeto.
Fachada
La fachada está estrechamente asociada con el Principio de diseño del conocimiento mínimo (Ley de Demeter). Facade es muy similar al adaptador. Ambos se envuelven, ambos asignan un objeto a otro, pero difieren en la intención. Fachada aplana la estructura compleja de un sujeto, gráfico de objetos complejos, simplificando el acceso a una estructura compleja.
Fachada envuelve una estructura compleja, proporcionándole una interfaz plana. Esto evita que el objeto del cliente se exponga a relaciones internas en la estructura del sujeto, promoviendo así un acoplamiento flojo.
Puente
Variante más compleja del patrón Adaptador donde no solo la implementación varía sino también la abstracción. Agrega una indirección más a la delegación. La delegación extra es el puente. Desacopla el adaptador incluso de la interfaz de adaptación. Aumenta la complejidad más que cualquier otro de los otros patrones de envoltura, así que aplique con cuidado.
Diferencias en constructores
Las diferencias de patrones también son obvias cuando se observan sus constructores.
Proxy no está envolviendo un objeto existente. No hay asignatura en constructor.
Decorator and Adapter sí envuelve el objeto ya existente, y normalmente se
proporciona en el constructor.
El constructor de fachadas toma el elemento raíz de un gráfico de objeto completo, de lo contrario, se ve igual que Adaptador.
Ejemplo de la vida real: JAXB Marshalling Adapter . El propósito de este adaptador es el mapeo de una clase plana simple a una estructura más compleja requerida externamente y para evitar la clase de sujeto "contaminante" con anotaciones excesivas.