Menu
Coddy logo textTech

Patrón Composite

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

El patrón Composite te permite tratar de manera uniforme los objetos individuales y los grupos de objetos. Compone objetos en estructuras de árbol donde tanto los elementos individuales como las colecciones de elementos comparten la misma interfaz. Es perfecto para representar jerarquías como sistemas de archivos, organigramas o componentes de UI.

El patrón tiene dos tipos de participantes: nodos Leaf (objetos individuales sin hijos) y nodos Composite (contenedores que contienen otros componentes). Ambos implementan una interfaz común Component:

abstract class FileSystemItem {
  String get name;
  int getSize();
  void display([String indent = '']);
}

class File implements FileSystemItem {
  @override
  final String name;
  final int size;

  File(this.name, this.size);

  @override
  int getSize() => size;

  @override
  void display([String indent = '']) {
    print('$indent- $name ($size KB)');
  }
}

class Folder implements FileSystemItem {
  @override
  final String name;
  final List<FileSystemItem> _children = [];

  Folder(this.name);

  void add(FileSystemItem item) => _children.add(item);

  @override
  int getSize() => _children.fold(0, (sum, item) => sum + item.getSize());

  @override
  void display([String indent = '']) {
    print('$indent+ $name/');
    for (var child in _children) {
      child.display('$indent  ');
    }
  }
}

void main() {
  var docs = Folder('Documents');
  docs.add(File('resume.pdf', 150));
  docs.add(File('photo.jpg', 2400));

  var projects = Folder('Projects');
  projects.add(File('main.dart', 25));
  docs.add(projects);

  docs.display();
  print('Total: ${docs.getSize()} KB');
}

La clase Folder puede contener tanto objetos File como otros objetos Folder. Cuando llamas a getSize() en una carpeta, esta calcula recursivamente el tamaño total de todo su contenido. El código cliente no necesita saber si está trabajando con un solo archivo o con una jerarquía de carpetas completa; ambos responden a los mismos métodos.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de organigrama usando el patrón Composite! Crearás una estructura en la que tanto los empleados individuales como los departamentos (que contienen empleados y otros departamentos) puedan tratarse de manera uniforme, perfecta para representar las jerarquías de una empresa.

Organizarás tu código en dos archivos:

  • organization.dart: Este archivo contiene tu interfaz de componente y las clases hoja y compuesta. Crea una clase abstracta OrganizationUnit con un getter name, un método getSalaryBudget() que devuelve un int y un método display([String indent = '']) para mostrar la jerarquía. Construye una clase Employee (la hoja) que implemente OrganizationUnit. Debe tener un nombre y un salario, y getSalaryBudget() debe devolver el salario del empleado. Su método display() debe imprimir [indent]- [name] ($[salary]). Después, crea una clase Department (la compuesta) que también implemente OrganizationUnit. Debe tener un nombre y mantener una lista de elementos secundarios OrganizationUnit. Añade un método add() para incluir empleados o subdepartamentos. Su método getSalaryBudget() debe sumar recursivamente los presupuestos de todos los elementos secundarios. Su método display() debe imprimir [indent]+ [name]/ y después mostrar cada elemento secundario con una indentación mayor (añade dos espacios).
  • main.dart: Importa tu archivo de organización y construye una estructura empresarial. Crea un departamento Engineering que contenga dos empleados: Alice con un salario de 80000 y Bob con un salario de 75000. Crea un departamento QA con un empleado: Carol con un salario de 65000. Ahora crea un departamento Technology y añade Engineering y QA como subdepartamentos. Llama a display() en el departamento Technology y después imprime Total Budget: $ seguido del presupuesto salarial total.

La belleza del patrón Composite es que Technology.getSalaryBudget() calcula automáticamente el total de todos los departamentos y empleados anidados; ¡el código cliente no necesita conocer la estructura interna!

Salida esperada:

+ Technology/
  + Engineering/
    - Alice ($80000)
    - Bob ($75000)
  + QA/
    - Carol ($65000)
Total Budget: $220000

Pruébalo tú mismo

import 'organization.dart';

void main() {
  // TODO: Crear un departamento de Ingeniería
  // TODO: Añadir a Alice con un salario de 80000
  // TODO: Añadir a Bob con un salario de 75000
  
  // TODO: Crear un departamento de QA
  // TODO: Añadir a Carol con un salario de 65000
  
  // TODO: Crear un departamento de Tecnología
  // TODO: Añadir Ingeniería y QA como subdepartamentos
  
  // TODO: Llamar a display() en el departamento de Tecnología
  
  // TODO: Imprimir "Total Budget: $" seguido del presupuesto total de salarios
}
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