Menu
Coddy logo textTech

Patrón Decorator

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy. Lección 96 de 110.

El patrón Decorator te permite añadir nuevos comportamientos a objetos de forma dinámica envolviéndolos en objetos especiales llamados decoradores. A diferencia de la herencia, que añade comportamiento en tiempo de compilación, los decoradores asignan responsabilidades adicionales en tiempo de ejecución sin modificar la clase original.

La idea clave es que tanto el objeto original como los decoradores implementan la misma interfaz.

Un decorador envuelve al objeto original, delega en él y añade su propio comportamiento antes o después:

abstract class Coffee {
  String getDescription();
  double getCost();
}

class SimpleCoffee implements Coffee {
  @override
  String getDescription() => 'Simple Coffee';

  @override
  double getCost() => 2.0;
}

class MilkDecorator implements Coffee {
  final Coffee _coffee;
  MilkDecorator(this._coffee);

  @override
  String getDescription() => '${_coffee.getDescription()}, Milk';

  @override
  double getCost() => _coffee.getCost() + 0.5;
}

class SugarDecorator implements Coffee {
  final Coffee _coffee;
  SugarDecorator(this._coffee);

  @override
  String getDescription() => '${_coffee.getDescription()}, Sugar';

  @override
  double getCost() => _coffee.getCost() + 0.2;
}

void main() {
  Coffee coffee = SimpleCoffee();
  coffee = MilkDecorator(coffee);
  coffee = SugarDecorator(coffee);

  print(coffee.getDescription());  // Simple Coffee, Milk, Sugar
  print(coffee.getCost());         // 2.7
}

Cada decorador envuelve al objeto anterior y lo mejora. Puedes apilar múltiples decoradores en cualquier combinación, creando un comportamiento flexible sin necesidad de crear una subclase para cada combinación posible. Este patrón es ideal cuando necesitas añadir características a los objetos sin afectar a otros objetos de la misma clase.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de pedidos de pizza usando el patrón Decorator! Crearás una pizza base que se puede mejorar con varios ingredientes, donde cada ingrediente envuelve al elemento anterior y añade algo tanto a la descripción como al precio.

Organizarás tu código en dos archivos:

  • pizza.dart: Este archivo contiene tu interfaz de pizza y todas las clases decoradoras. Comienza con una clase abstracta Pizza que define dos métodos: String getDescription() y double getPrice(). Después, crea una clase PlainPizza que implemente Pizza: devuelve Plain Pizza como descripción y cuesta 8.0. Ahora crea tres clases decoradoras, cada una de las cuales envuelve una Pizza y la mejora:
    • CheeseDecorator: añade , Cheese a la descripción y 1.5 al precio
    • PepperoniDecorator: añade , Pepperoni a la descripción y 2.0 al precio
    • MushroomDecorator: añade , Mushrooms a la descripción y 1.25 al precio
    Cada decorador debe implementar Pizza, aceptar una Pizza en su constructor y delegar en la pizza envuelta antes de añadir su propia contribución.
  • main.dart: Importa tu archivo de pizza y demuestra cómo los decoradores se apilan para crear un pedido personalizado. Comienza con una PlainPizza, después envuélvela con CheeseDecorator, después envuelve esa con PepperoniDecorator y, finalmente, envuelve todo con MushroomDecorator. Imprime la descripción final de la pizza y después imprime Total: $ seguido del precio.

Observa cómo cada decorador se basa en el anterior: ¡estás creando una pizza completamente cargada al apilar decoradores sencillos y con una única responsabilidad!

Salida esperada:

Plain Pizza, Cheese, Pepperoni, Mushrooms
Total: $12.75

Pruébalo tú mismo

import 'pizza.dart';

void main() {
  // TODO: Crear una PlainPizza
  
  // TODO: Envolverla con CheeseDecorator
  
  // TODO: Envolver eso con PepperoniDecorator
  
  // TODO: Envolver todo con MushroomDecorator
  
  // TODO: Imprimir la descripción final de la pizza
  
  // TODO: Imprimir "Total: $" seguido del precio
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Dart online