2008-11-07 13 views
13

Suponiendo que tengo una clase llamada A, y quiero utilizar el patrón de diseño del decorador. Corrígeme si estoy equivocado, pero para que funcione, necesitaremos crear una clase de decorador, digamos ADecorator, que mantendrá una referencia a una instancia de A, y todos los demás decoradores extenderán esto para agregar funcionalidad.¿Por qué necesitamos el decorador en el patrón de diseño del decorador?

No entiendo por qué tenemos que crear una clase de decorador, en lugar de usar una instancia de A?

Respuesta

25

El patrón de decorador se utiliza para agregar capacidades a los objetos dinámicamente (es decir, en tiempo de ejecución). Normalmente, el objeto tendrá sus capacidades corregidas cuando escriba la clase. Pero un punto importante es que la funcionalidad del objeto se extiende de forma transparente para el cliente del objeto porque implementa la misma interfaz que el objeto original que delega la responsabilidad del objeto decorado.

El patrón de decorador funciona en escenarios donde hay muchas funciones opcionales que un objeto puede tener. Sin el patrón de decorador, deberá crear una clase diferente para cada configuración de opción de objeto. Un ejemplo que es bastante útil proviene del Head First Design Patterns libro de O'Reilly. Utiliza un ejemplo de cafetería que suena como StarBucks.

Así que tiene el café básico con un método como el costo.

public double cost(){ 
    return 3.45; 
} 

A continuación, el cliente puede agregar la crema que cuesta 0,35 por lo que ahora crea una clase CoffeeCream con el método de costo:

public double cost(){ 
    return 3.80; 
} 

A continuación, el cliente lo desea, puede Mocha, que cuesta 0,5, y es posible que quieran Mocha con crema o moca sin crema. Entonces creas las clases CoffeeMochaCream y CoffeeMocha. Entonces un cliente quiere crema doble para que crees una clase de CoffeeCreamCream ... etc. Lo que terminas con explosión de clase. Disculpe el pobre ejemplo utilizado. Es un poco tarde y sé que es trivial pero expresa el punto.

su lugar se puede crear una clase abstracta de artículos con un método de costo abstracta:

public abstract class Item{ 
    public abstract double cost(); 
} 

Además, puede crear una clase de café de hormigón que se extiende artículo:

public class Coffee extends Item{ 
    public double cost(){ 
     return 3.45; 
    } 
} 

A continuación, se crea un CoffeeDecorator que extiende la misma interfaz y contiene un artículo.

public abstract class CoffeeDecorator extends Item{ 
    private Item item; 
    ... 
} 

continuación, puede crear decoradores concretas para cada opción:

public class Mocha extends CoffeeDecorator{ 

    public double cost(){ 
    return item.cost() + 0.5; 
    } 

} 

Note como el decorador no le importa qué tipo de objeto se está terminando con tal de que se trata de un artículo? Utiliza el costo() del objeto del artículo y simplemente agrega su propio costo.

public class Cream extends CoffeeDecorator{ 

    public double cost(){ 
    return item.cost() + 0.35; 
    } 

} 

Ahora bien, es posible que un gran número de configuraciones con estas pocas clases: por ejemplo,

Item drink = new Cream(new Mocha(new Coffee))); //Mocha with cream 

o

Item drink = new Cream(new Mocha(new Cream(new Coffee))));//Mocha with double cream 

Y así sucesivamente.

+0

Aha, supongo que usted es un lector de Head First Design Patterns? – dhiller

+0

Encontré esta respuesta más fácil de comprender que el artículo de Wikipedia. –

+0

@dhiller Yep. Design Patterns fue el primero que probé y comencé a recomendarlos a todos mis alumnos. –

5

No puedo explicarlo mejor que el artículo wikipedia.

+0

Eso casi suena como una respuesta sarcástica, pero luego fui y miré el artículo de Wikipedia y sí, es excelente. Charada, todo lo que alguna vez quisiste saber está ahí, ¡incluyendo quién, qué, cuándo, dónde y cómo! –

+0

Lo siento si suena sarcástico, pero el inglés no es mi lengua materna, por lo que ese tipo de "accidentes" está destinado a suceder :-) – Kasper

2

En algunos idiomas (como Ruby o JavaScript), puede agregar nuevas funciones a una instancia A. Noté que tu pregunta está etiquetada como Java, así que supongo que estás preguntando por qué no puedes hacer esto en Java. La razón es que Java está tipado estáticamente. Una instancia A solo puede tener los métodos que la clase A define o hereda. Por lo tanto, si desea en tiempo de ejecución dar a una instancia A un método que A no define, entonces este nuevo método debe definirse en una clase diferente.

3

Por cierto, si recién está comenzando con los patrones, el libro de patrones de diseño de Head First es fenomenal. Realmente hace que los conceptos sean simples de digerir, y se asegura de contrastar y comparar patrones similares de una manera que es ridículamente fácil de entender.

+0

Tengo que decir esto, el libro es increíble. De hecho, el ejemplo del café anterior está tomado de ese libro, pero el libro toma ese ejemplo mucho más. –

Cuestiones relacionadas