oop - reusable - Generador contra decorador
factory pattern (4)
Desde cuándo usarías el patrón de construcción? ,
Se dice que el patrón del generador es apropiado para el ejemplo de Pizza.
¿Por qué no decorador? al tratar el queso, el pepperoni y el tocino como decoraciones adicionales en una pizza base.
Es por la razón que el queso / los pepperoni deben construirse por separado. No creo, deben construirse por separado, ya que pueden estar disponibles readymade.
Pls aclarar. También estoy buscando un buen ejemplo de patrón decorador en el mundo real y por qué es el adecuado para ese ejemplo en particular. Gracias.
Del artículo del patrón de decorador de wikipedia:
En la programación orientada a objetos, el patrón decorador es un patrón de diseño que permite agregar un comportamiento nuevo / adicional a un objeto existente de forma dinámica.
No es necesario agregar toppings a una pizza una vez que se haya construido por completo. No comas media pizza y luego agrega otra cubierta.
En otras palabras, el Patrón del constructor facilita la construcción de un objeto que sea extensible en direcciones independientes en el momento de la construcción, mientras que el Patrón del decorador le permite agregar extensiones a la funcionalidad de un objeto después del tiempo de construcción. Usar el patrón de decorador para construir objetos es malo porque deja al objeto en un estado inconsistente (o al menos incorrecto) hasta que todos los decoradores necesarios estén en su lugar, similar al problema de JavaBean de usar setters para especificar argumentos de constructor opcionales.
El patrón del generador se usa específicamente para compilar y Decorator para agregar funciones especiales después de la compilación. Por ejemplo, en el ejemplo de Pizza anterior, podemos decidir utilizar uno de los dos patrones en función del dominio del problema.
Si los copos de chile son esenciales para una pizza y de manera similar tenemos muchos ingredientes para agregar a la pizza, de los cuales pocos son elementales para hacer que la pizza sea comestible (estado significativo), podemos preferir usar el constructor. Una vez que se construye la pizza, podemos ir y decorarla con diferentes ingredientes como salsa de tomate, aceitunas, etc.
Además, se indicó anteriormente correctamente que se pueden usar juntos, pero esto aumentará la complejidad. Por lo tanto, debemos usar patrones sabiamente solo cuando sea necesario en el dominio del problema, de lo contrario bastará una simple construcción.
Estás confundiendo dos cosas muy diferentes. GoF clasifica el Constructor como un patrón de creación, mientras que el Decorador es un patrón estructural. Se describen de la siguiente manera (Gamma et al, página 1):
Constructor (97) Separe la construcción de un objeto complejo de su representación para que el mismo proceso de construcción pueda crear diferentes representaciones.
Decorador (175) Adjunte responsabilidades adicionales a un objeto dinámicamente. Los decoradores proporcionan una alternativa flexible a las subclases para ampliar la funcionalidad.
Tenga en cuenta el énfasis en el decorador. Es una alternativa flexible a la subclasificación. La subclasificación se usa para modelar una relación is-a . El queso no es una pizza. La pizza se compone de varios ingredientes, y generalmente se modela usando la composición.
El patrón del constructor es relevante aquí porque hay una cantidad tan grande de ingredientes que surge la necesidad de construirlos de manera estandarizada.
Para tomar un ejemplo del mundo real de un decorador, recientemente quise registrar las consultas ejecutadas usando jdbc en mi aplicación java. Lo logré implementando una clase llamada LoggingConnection que extendió la interfaz de Connection.
public class LoggingConnection implements Connection
{
public static class LogEntry
{
public String sql;
public int invocationCount;
public double avgTime;
public double maxTime;
}
private Connection delegate;
private Map<String, LogEntry> log;
public LoggingConnection(Connection delegate)
{
this.delegate = delegate;
this.log = new HashMap<String, LogEntry>();
}
public Map<String, LogEntry> getLog()
{
return log;
}
@Override
public void clearWarnings()
throws SQLException
{
delegate.clearWarnings();
}
@Override
public void close()
throws SQLException
{
delegate.close();
}
// forwarding declarations to all other methods declared in the interface
...
}
Esto me permite aprobar una implementación concreta de una conexión y ampliar su funcionalidad en tiempo de ejecución. La creación de subclases sería problemática en este contexto, ya que no necesariamente se sabe qué objeto de conexión realmente se devuelve. Esto se debe a que está construido para ti usando la fábrica DriverManager:
Connection conn = DriverManger.getConnection(dsn);
El objeto conn es en este caso una implementación contenida en el controlador, del que generalmente no conozco el nombre. El objetivo del enfoque de decorador es que no tengo que saberlo, y que no está vinculado a una implementación específica.
Veamos las características clave de Builder and Decorator .
Builder : (Un patrón de creación)
- Demasiados argumentos para pasar del programa cliente a la clase Factory que pueden ser propensos a errores
- Algunos de los parámetros pueden ser opcionales a diferencia de Factory, que obliga a enviar todos los parámetros
- El objeto es pesado y su creación es compleja. por ejemplo, construir varios tipos de pizzas
Decorator : (Un patrón estructural)
- Agregue comportamiento a objeto en tiempo de ejecución. La herencia es la clave para lograr esta funcionalidad, que es a la vez ventaja y desventaja de este patrón.
- Mejora el comportamiento de la interfaz.
- Decorator se puede ver como un compuesto degenerado con solo un componente. Sin embargo, un Decorador agrega responsabilidades adicionales, no está destinado a la agregación de objetos.
- Decorator admite composición recursiva
- Decorator está diseñado para permitirle agregar responsabilidades a objetos sin subclasificar
Cuándo usar Decorator :
- Las responsabilidades y comportamientos del objeto se deben agregar / eliminar dinámicamente
- Implementaciones concretas deben estar desacopladas de las responsabilidades y comportamientos
- Cuando la subclasificación es demasiado costosa para agregar / eliminar dinámicamente responsabilidades
Volviendo a su consulta:
El constructor tiene el patrón de creación correcto para Pizza. La pizza se crea con ingredientes obligatorios inicialmente (pan, etc.). El queso, el pepperoni y el tocino son ingredientes opcionales, pero aún así pueden formar parte de la pizza durante el proceso de fabricación.
Decorator es útil para agregar responsabilidades dinámicas en el tiempo de ejecución para objetos ya creados.
p.ej :
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));
Consulte las publicaciones a continuación para obtener más detalles:
Mantener el constructor en una clase separada (interfaz fluida)