Menu
Coddy logo textTech

Composite-Muster

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 99 von 110.

Das Composite-Muster ermöglicht es dir, einzelne Objekte und Gruppen von Objekten einheitlich zu behandeln. Es setzt Objekte zu Baumstrukturen zusammen, in denen sowohl einzelne Elemente als auch Sammlungen von Elementen dieselbe Schnittstelle verwenden. Das eignet sich hervorragend zur Darstellung von Hierarchien wie Dateisystemen, Organigrammen oder UI-Komponenten.

Das Muster hat zwei Arten von Beteiligten: Blatt-Knoten (einzelne Objekte ohne untergeordnete Elemente) und Kompositum-Knoten (Container, die andere Komponenten enthalten). Beide implementieren eine gemeinsame Komponente-Schnittstelle:

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');
}

Die Klasse Folder kann sowohl File-Objekte als auch andere Folder-Objekte enthalten. Wenn Sie getSize() für einen Ordner aufrufen, berechnet sie rekursiv die Gesamtgröße seines gesamten Inhalts. Der Client-Code muss nicht wissen, ob er mit einer einzelnen Datei oder einer gesamten Ordnerhierarchie arbeitet – beide reagieren auf dieselben Methoden.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Organisationsdiagrammsystem mit dem Composite-Muster! Du erstellst eine Struktur, in der sowohl einzelne Mitarbeiter als auch Abteilungen (die Mitarbeiter und weitere Abteilungen enthalten) einheitlich behandelt werden können – perfekt zur Darstellung von Unternehmenshierarchien.

Du organisierst deinen Code in zwei Dateien:

  • organization.dart: Diese Datei enthält deine Komponentenschnittstelle sowie die Blatt- und Verbundklassen. Erstelle eine abstrakte Klasse OrganizationUnit mit einem name-Getter, einer getSalaryBudget()-Methode, die ein int zurückgibt, und einer display([String indent = ''])-Methode zur Darstellung der Hierarchie. Erstelle eine Employee-Klasse (das Blatt), die OrganizationUnit implementiert. Sie sollte einen Namen und ein Gehalt besitzen, wobei getSalaryBudget() das Gehalt des Mitarbeiters zurückgibt. Ihre display()-Methode sollte [indent]- [name] ($[salary]) ausgeben. Erstelle anschließend eine Department-Klasse (den Verbund), die ebenfalls OrganizationUnit implementiert. Sie sollte einen Namen besitzen und eine Liste von OrganizationUnit-Kindern verwalten. Füge eine add()-Methode hinzu, um Mitarbeiter oder Unterabteilungen aufzunehmen. Ihre getSalaryBudget()-Methode sollte rekursiv die Budgets aller Kinder summieren. Ihre display()-Methode sollte [indent]+ [name]/ ausgeben und anschließend jedes Kind mit einer größeren Einrückung darstellen (zwei Leerzeichen hinzufügen).
  • main.dart: Importiere deine Organisationsdatei und erstelle eine Unternehmensstruktur. Erstelle eine Engineering-Abteilung mit zwei Mitarbeitern: Alice mit einem Gehalt von 80000 und Bob mit einem Gehalt von 75000. Erstelle eine QA-Abteilung mit einem Mitarbeiter: Carol mit einem Gehalt von 65000. Erstelle nun eine Technology-Abteilung und füge sowohl Engineering als auch QA als Unterabteilungen hinzu. Rufe display() für die Technology-Abteilung auf und gib anschließend Total Budget: $ gefolgt vom Gesamtgehaltsbudget aus.

Das Schöne am Composite-Muster ist, dass Technology.getSalaryBudget() automatisch die Gesamtsumme über alle verschachtelten Abteilungen und Mitarbeiter berechnet – der Client-Code muss die interne Struktur nicht kennen!

Erwartete Ausgabe:

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

Probier es selbst

import 'organization.dart';

void main() {
  // TODO: Erstelle eine Engineering-Abteilung
  // TODO: Füge Alice mit einem Gehalt von 80000 hinzu
  // TODO: Füge Bob mit einem Gehalt von 75000 hinzu
  
  // TODO: Erstelle eine QA-Abteilung
  // TODO: Füge Carol mit einem Gehalt von 65000 hinzu
  
  // TODO: Erstelle eine Technology-Abteilung
  // TODO: Füge Engineering und QA als Unterabteilungen hinzu
  
  // TODO: Rufe display() für die Technology-Abteilung auf
  
  // TODO: Drucke "Total Budget: $" gefolgt vom gesamten Gehaltsbudget
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Dart-Compiler