2011-01-22 33 views
33

De When would you use the Builder Pattern?,Constructor Vs Decorator

Se dice que Builder es apropiado para pizza ejemplo.

¿Por qué no Decorator? mediante el tratamiento de queso, pepperoni, tocino como decoraciones adicionales en una pizza base.

Es por la razón que los Quesos/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 apto para ese ejemplo en particular. Gracias.

+0

que tenían el mismo pensamiento cuando me enteré de esto con el ejemplo. El profesor no pudo ayudarme, pero esto sí, ¡gracias! – Mene

Respuesta

36

Del artículo Decorator de Wikipedia:

En la programación orientada a objetos, el patrón decorador es un patrón de diseño que permite nueva/comportamiento adicional que se añade a un objeto existente dinámicamente.

No es necesario agregar toppings a una pizza después de que se haya construido por completo. No comas media pizza y luego agrega otra cubierta.

En otras palabras, el Builder hace que sea fácil de construir un objeto que es extensible en direcciones independientes en el tiempo de construcción, mientras que el Decorator le permite agregar extensiones de funcionalidad a un objeto después de 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.

+1

potter: De hecho, algunos aderezos como kitchup, hojuelas de chile se darán junto con Pizza. Entonces, ¿podemos decir que aplicamos ambos patrones? ¿Primero constructor luego Decorador? – bjskishore123

+0

alfarero: +1, mi hipótesis anterior parece ser correcta sobre los ingredientes, obtenida de http://stackoverflow.com/questions/2707401/please-help-me-understand-the-decorator-pattern-with-real-world- ejemplo – bjskishore123

+3

@bjs: sí, el decorador y el constructor pueden combinarse con sensatez, y su ejemplo es una posibilidad; sin embargo, conduce a un diseño complejo y un código menos legible. Solo usaría Builder + Decorator si estuviera seguro de que en realidad lo requería el proyecto y no solo un caso de "Pattern Fever" de mi parte.Considere si valdría la pena simplemente agregar un método 'addChilli()' a la clase base en lugar de construir un 'ChilliDecorator' completo. (Como siempre, no hay una respuesta correcta.) –

20

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 como sigue (Gamma et al, página 1):

Generador de (97) Separar la construcción de un objeto complejo de su representación para que el mismo proceso de construcción puede crear diferentes representaciones.

Decorador (175) Agregue 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. Las subclases se usan para modelar una relación is-a. El queso no es una pizza. La pizza es compuesta de una serie de ingredientes, y que generalmente se modela utilizando composición.

El patrón del generador es relevante aquí porque hay una gran cantidad de ingredientes que se necesitan para 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 usted, utilizando la fábrica DriverManager:

objeto
Connection conn = DriverManger.getConnection(dsn); 

El conn es en este caso una aplicación contenida en el controlador, que generelly no sé el nombre de. El objetivo del enfoque de decorador es que no tengo que saberlo, y que no está vinculado a una implementación específica.

+1

Bueno, una "alternativa" sugiere que las subclases también podrían usarse. La alternativa de subclases no es hacer que el queso sea una subclase de pizza, sino tener una subclase de pizza de queso _pizza_. Como una pizza de queso es una pizza. –

+0

@ Lèse: Pero es concebible que pueda implementar un decorador que agregue la misma funcionalidad de "queso" como lo hace una subclase. La única diferencia importante sería que puede decidir hacer la extensión en tiempo de ejecución en su lugar. –

+0

+1: Útil, gracias. – bjskishore123

1

El patrón del constructor se usa específicamente para construir y Decorator para agregar características especiales después de la compilación. e.g 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 la pizza 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 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.

2

Veamos las características clave de Generador y Decorador.

Builder: (Un patrón creacional)

  1. demasiados argumentos para pasar de programa cliente para la clase de fábrica que puede ser propenso a errores
  2. Algunos de los parámetros pueden ser opcionales a diferencia de fábrica que las fuerzas de envíe todos los parámetros
  3. El objeto es pesado y su creación es compleja. p.ej. la construcción de diversos tipos de pizzas

Decorator: (Un modelo estructural)

  1. Añadir comportamiento a oponerse 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.
  2. Mejora el comportamiento de la interfaz.
  3. El decorador puede verse como un compuesto degenerado con un solo componente. Sin embargo, un Decorador agrega responsabilidades adicionales, no está destinado a la agregación de objetos.
  4. decorador apoya composición recursiva
  5. decorador está diseñado para permitir añadir responsabilidades a objetos sin subclasificar

Cuándo utilizar decorador:

  1. responsabilidades objeto y los comportamientos se deben agregar/eliminar dinámicamente
  2. implementaciones de concreto deben ser desacoplados de responsabilidades y comportamientos
  3. Cuando sub - classing es demasiado costoso para añadir dinámicamente/quitar responsabilidades

volver a su consulta:

Constructor es el patrón creacional adecuado 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.

Decorador 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 a continuación los mensajes para más detalles:

Keeping builder in separate class (fluent interface)

When to Use the Decorator Pattern?

Cuestiones relacionadas