que programacion practicos patrones patron estructural ejemplos ejemplo diseño decorador cafe c# .net design-patterns inheritance decorator

c# - programacion - patrones de diseño ejemplos practicos



Patrón Decorador vs Herencia con ejemplos (4)

He estado experimentando con el patrón de decorador para ampliar la funcionalidad del código que no desea tocar, por ejemplo, y veo cómo implementarlo; sin embargo, ahora no estoy seguro de por qué no hereda de la clase original y se extiende de esa manera.

He leído que el patrón de decorador le permite agregar funcionalidad en tiempo de ejecución, mientras que la herencia significa que está allí en tiempo de compilación.

No entiendo esto.

¿Podría alguien explicar esto, dar ejemplos y explicar cuándo es mejor utilizar el decorador frente a la herencia?

Gracias


Como otros ya han dicho, los decoradores son buenos para agregar "opciones" a las cosas ... Los beneficios vienen en la forma en que puedes encadenar métodos, etc. a través de los decoradores.

Imagina que compro un auto con opciones de interior de cuero, pintura metálica y un impresionante spoiler ...

Hay 8 combinaciones diferentes de las tres opciones, pero con decoradores solo necesitas tres clases adicionales.

Sin embargo, lo interesante es la forma en que funciona el patrón decorador. Como un breve ejemplo:

public class MetallicPaint : Car { private Car car; public MetallicPaint(Car wrappedCar) { car = wrappedCar; } public decimal Cost() { return car.Cost() + 500; } public string Description() { return car.Description() + ", Metallic Paint"; } public string Speed() { return car.Speed(); } [... {pass through other methods and properties to the car object}] }

Este no es un ejemplo completo, pero resalta cómo el decorador puede interactuar con el objeto que está decorando. Y, por supuesto, debido a que implementa el automóvil, puede usarse como un automóvil de cualquier otro modo (y pasa por cualquier cosa que el decorador no afecte al objeto interior del automóvil).

Por supuesto, si tuviera varios de estos decoradores con un auto anidado dentro de cada uno, a su vez agregaría su costo, su parte de la descripción y tal vez el alerón alteraría la velocidad mientras que los otros no ...

En esencia, le permite modificar un objeto de una manera mucho más modular y menos fundamental que la herencia. Los decoradores siempre se deben usar como si fueran el objeto base (en este caso, Car ), por lo que nunca deberían exponer ningún nuevo método o propiedad, solo cambiar ligeramente el efecto de los existentes.


El patrón decorador es mejor que la herencia si tiene muchas características para agregar y también necesita tener una combinación de estas características. Supongamos que su clase base es A, y desea extender (decorar) esta clase base con la función f1, f2, f3, f4 y alguna combinación de ellas como (f1, f2) y (f1, f3) y ...; por lo que necesitaría crear 4! = 4 * 3 * 2 * 1 = 24 clase en su jerarquía (4 para cada característica y el resto para su combinación). Mientras que, usando un patrón decorativo, ¡solo necesitarías crear 4 clases!

para @Seyed Morteza Mousavi en @Razvi post: Tiene razón, podemos agregar dos propiedades Desplazable y Bordeado para ver la clase, luego verificamos si la propiedad está establecida en verdadero, así que ejecute el comportamiento deseado. Pero esto requiere que ya estemos al tanto del número de la función que necesitamos (que no es el caso en el patrón de decorador). de lo contrario, con cada característica nueva (digamos f1) que queremos agregar a nuestra clase, tenemos que alterar nuestra clase principal, o heredar la clase principal (diría) y agregar la propiedad. Tomando este último enfoque, necesitaría modificar la parte del código que maneja la combinación de características (esto no es bueno, ya que no está obedeciendo la regla general de "acoplamiento libre").

espero que esto ayude.


Imagine un juego como Civilization, donde cada cuadrado del mapa puede tener una variedad de recursos asociados (como, por ejemplo, varios minerales, madera, petróleo, etc.).

Si utilizó la herencia directa, necesitaría crear una clase para cada tipo de cuadrado. Sería difícil de tener

public class OilSquare {} public class OilAndGoldSquare {} public class GoldAndSilverSquare {} // etc.

El patrón decorador permite mezclar y combinar sin necesidad de crear una jerarquía rígida. Entonces, tendrías en cambio:

public class Square {} public class GoldDec {} public class SilverDec {} public class OilDec {} // ... var crazyMix = new GoldDec(new SilverDec(new OilDec(new Square())));

Dicho de otra manera, los decoradores permiten la creación de un comportamiento de tubería, con cada paso en la tubería que se puede intercambiar con otro paso.


Supongamos que crea una clase View que muestra sus elementos de una determinada manera. Ahora decide que también quiere una versión que se pueda desplazar, por lo que crea un Vista desplazable que hereda la Vista. Más tarde, usted decide que también quiere una versión con borde, por lo que ahora necesita hacer BorderedView y BorderdScrollableView.

Si, por otro lado, puede hacer un decorador para cada estilo agregado. Tendría las siguientes clases:

  • Ver
  • ScrollableDecorator
  • BorderedDecorator

Cuando quiere una vista de desplazamiento con borde, lo hace:

new BorderedDecorator(new ScrollableDecorator(new View())) .

Entonces puede configurar cualquier combinación de esto con solo las 3 clases. Y puede agregarlos o eliminarlos en el tiempo de ejecución (supongamos que hace clic en un botón que dice agregar borde, ahora ajusta su vista con un BorderDecorator ... mientras que con la herencia necesita implementar esta clase de vista si no lo ha hecho ya, o necesita crear una nueva instancia de vista y copiar todos los datos relevantes de la primera vista a la segunda vista, lo cual no es tan fácil de hacer como simplemente agregar o eliminar envoltorios).