Menu
Coddy logo textTech

Patron Composite

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy. Leçon 99 sur 110.

Le patron Composite vous permet de traiter uniformément les objets individuels et les groupes d’objets. Il compose les objets en structures arborescentes où les éléments individuels comme les collections d’éléments partagent la même interface. C’est idéal pour représenter des hiérarchies telles que les systèmes de fichiers, les organigrammes ou les composants d’interface utilisateur.

Le modèle comporte deux types de participants : les nœuds Leaf (objets individuels sans enfants) et les nœuds Composite (conteneurs qui contiennent d’autres composants). Les deux implémentent une interface Component commune :

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 classe Folder peut contenir à la fois des objets File et d'autres objets Folder. Lorsque vous appelez getSize() sur un dossier, elle calcule de manière récursive la taille totale de tout son contenu. Le code client n'a pas besoin de savoir s'il travaille avec un seul fichier ou une hiérarchie complète de dossiers - les deux répondent aux mêmes méthodes.

challenge icon

Défi

Facile

Construisons un système d’organigramme à l’aide du pattern Composite ! Vous allez créer une structure dans laquelle les employés individuels et les services (qui contiennent des employés et d’autres services) peuvent être traités uniformément — ce qui est parfait pour représenter les hiérarchies d’une entreprise.

Vous allez organiser votre code en deux fichiers :

  • organization.dart : Ce fichier contient votre interface de composant ainsi que les classes feuille et composite. Créez une classe abstraite OrganizationUnit avec un getter name, une méthode getSalaryBudget() qui renvoie un int, et une méthode display([String indent = '']) pour afficher la hiérarchie. Construisez une classe Employee (la feuille) qui implémente OrganizationUnit. Elle doit posséder un nom et un salaire, et getSalaryBudget() doit renvoyer le salaire de l’employé. Sa méthode display() doit afficher [indent]- [name] ($[salary]). Créez ensuite une classe Department (le composite) qui implémente également OrganizationUnit. Elle doit posséder un nom et gérer une liste d’enfants OrganizationUnit. Ajoutez une méthode add() pour inclure des employés ou des sous-services. Sa méthode getSalaryBudget() doit additionner récursivement les budgets de tous les enfants. Sa méthode display() doit afficher [indent]+ [name]/, puis afficher chaque enfant avec une indentation accrue (ajoutez deux espaces).
  • main.dart : Importez votre fichier d’organisation et construisez une structure d’entreprise. Créez un service Engineering contenant deux employés : Alice avec un salaire de 80000 et Bob avec un salaire de 75000. Créez un service QA avec un employé : Carol avec un salaire de 65000. Créez maintenant un service Technology et ajoutez Engineering et QA comme sous-services. Appelez display() sur le service Technology, puis affichez Total Budget: $ suivi du budget salarial total.

L’intérêt du pattern Composite est que Technology.getSalaryBudget() calcule automatiquement le total de tous les services et employés imbriqués — le code client n’a pas besoin de connaître la structure interne !

Sortie attendue :

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

Essayez vous-même

import 'organization.dart';

void main() {
  // TODO : Créer un département Ingénierie
  // TODO : Ajouter Alice avec un salaire de 80000
  // TODO : Ajouter Bob avec un salaire de 75000
  
  // TODO : Créer un département QA
  // TODO : Ajouter Carol avec un salaire de 65000
  
  // TODO : Créer un département Technologie
  // TODO : Ajouter Ingénierie et QA en tant que sous-départements
  
  // TODO : Appeler display() sur le département Technologie
  
  // TODO : Afficher "Total Budget: $" suivi du budget salarial total
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Dart en ligne