Decorator patrón cambia dinámicamente la funcionalidad de un objeto en tiempo de ejecución sin afectar la funcionalidad existente de los objetos.
casos de uso clave:
- Añadir funcionalidades/responsabilidades adicionales dinámicamente
- Eliminar funcionalidades/responsabilidades dinámicamente
- evitar el exceso de subclasificar para agregar responsabilidades adicionales .
inconvenientes:
- El uso excesivo de principio abierto cerrado (abierto para la extensión y cerrado para la modificación). Use esta característica con moderación, donde el código es menos probable que cambie.
- Demasiadas clases pequeñas y agregarán gastos generales de mantenimiento.
Un ejemplo del mundo real: Calcular el precio de la bebida, que puede contener múltiples sabores.
abstract class Beverage {
protected String name;
protected int price;
public Beverage(){
}
public Beverage(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
protected void setPrice(int price){
this.price = price;
}
protected int getPrice(){
return price;
}
protected abstract void decorateBeverage();
}
class Tea extends Beverage{
public Tea(String name){
super(name);
setPrice(10);
}
public void decorateBeverage(){
System.out.println("Cost of:"+ name +":"+ price);
// You can add some more functionality
}
}
class Coffee extends Beverage{
public Coffee(String name){
super(name);
setPrice(15);
}
public void decorateBeverage(){
System.out.println("Cost of:"+ name +":"+ price);
// You can add some more functionality
}
}
abstract class BeverageDecorator extends Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage){
this.beverage = beverage;
setName(beverage.getName()+"+"+getDecoratedName());
setPrice(beverage.getPrice()+getIncrementPrice());
}
public void decorateBeverage(){
beverage.decorateBeverage();
System.out.println("Cost of:"+getName()+":"+getPrice());
}
public abstract int getIncrementPrice();
public abstract String getDecoratedName();
}
class SugarDecorator extends BeverageDecorator{
public SugarDecorator(Beverage beverage){
super(beverage);
}
public void decorateBeverage(){
super.decorateBeverage();
decorateSugar();
}
public void decorateSugar(){
System.out.println("Added Sugar to:"+beverage.getName());
}
public int getIncrementPrice(){
return 5;
}
public String getDecoratedName(){
return "Sugar";
}
}
class LemonDecorator extends BeverageDecorator{
public LemonDecorator(Beverage beverage){
super(beverage);
}
public void decorateBeverage(){
super.decorateBeverage();
decorateLemon();
}
public void decorateLemon(){
System.out.println("Added Lemon to:"+beverage.getName());
}
public int getIncrementPrice(){
return 3;
}
public String getDecoratedName(){
return "Lemon";
}
}
public class VendingMachineDecorator {
public static void main(String args[]){
Beverage beverage = new SugarDecorator(new LemonDecorator(new Tea("Assam Tea")));
beverage.decorateBeverage();
beverage = new SugarDecorator(new LemonDecorator(new Coffee("Cappuccino")));
beverage.decorateBeverage();
}
}
de salida:
Cost of:Assam Tea:10
Cost of:Assam Tea+Lemon:13
Added Lemon to:Assam Tea
Cost of:Assam Tea+Lemon+Sugar:18
Added Sugar to:Assam Tea+Lemon
Cost of:Cappuccino:15
Cost of:Cappuccino+Lemon:18
Added Lemon to:Cappuccino
Cost of:Cappuccino+Lemon+Sugar:23
Added Sugar to:Cappuccino+Lemon
En este ejemplo se calcula el costo de bebidas en la máquina expendedora después de añadir muchos sabores a la bebida.
En el ejemplo anterior:
coste de la TEA = 10, limón y azúcar = 3 = 5. Si hacer Azúcar + limón + Té, cuesta 18.
Costo de café = 15, Limón = 3 y Sugar = 5. Si prepara Sugar + Lemon + Coffee, cuesta 23
Al usar el mismo Decorator para ambas bebidas (té y café), se ha reducido el número de subclases. En ausencia del patrón Decorator, debe tener diferentes subclases para diferentes combinaciones.
Las combinaciones serán así:
SugarLemonTea
SugarTea
LemonTea
SugarLemonCapaccuino
SugarCapaccuino
LemonCapaccuino
etc.
Mediante el uso mismo decorador para ambas bebidas, el número de sub-clases se han reducido. Es posible debido a composición en lugar de herencia concepto utilizado en este patrón. pregunta
SE relacionadas:
Decorator Pattern for IO
Enlaces de interés:
design-patterns-decorator por DZone
decorator por sourcemaking
oodesign artículo
De manera similar, las transmisiones de Java son solo una colección gigante de decoradores que decoran decoradores que han decorado algo que decora. Mi cara simplemente se derritió. –
Pensé que los streams serían un mejor ejemplo que el ejemplo de café en mi libro Head First: Design Patterns en mi escritorio. –
¿Alguien puede explicar por qué el patrón de decorador es la solución óptima para esta situación? –