UML-Klassendiagramm Objektbeziehungen - Assoziationen

https://bildung.social/@oerinformatik/110425552692026065

https://oer-informatik.de/uml-klassendiagramm-assoziation

UML, Klassendiagramm, Assoziation, Aggregation, Komposition, Multiplizität, Navigierbarkeit, Abhängigkeit, Rollennamen, Beobachter-Muster

tl/dr; (ca. 33 min Lesezeit): Mit einzelnen Objekten erreicht man in der objektorientierten Programmierung (OOP) noch nicht viel. Erst im Zusammenspiel als Objektsammlungen und über Objektinteraktionen entwickelt die OOP ihre Stärken. Der folgende Text behandelt die Fragen: Welche Objektbeziehungen gibt es? Was unterscheidet Abhängigkeit, Assoziation, Aggregation und Komposition? Wie liest und begründet man Multiplizitäten, und woran erkennt man die passende Beziehung in Anforderungstexten, Quelltexten und Entwurfsmustern? Versuch der Klärung [AI-Assisted]. (Zuletzt geändert am 29.10.2026)

Dieser Artikel ist Teil einer Artikelreihe über UML-Klassendiagramme: Einstieg in das Klassendiagramm (Übung Ticketautomat, Übungsaufgaben) / Sichtbarkeitsmodifikatoren / Assoziation, Aggregation, Komposition (Übungsaufgaben) / Vererbung (Übungsaufgaben) / Abstrakte Klassen und Interfaces / Polymorphie (Übungsaufgaben). Dazu: Klassendiagramme mit PlantUML zeichnen und Objektdiagramm.

Schon fit in diesem Thema? Nutze die Kann-Liste und die Leitfragen unter dem Artikel als Checkliste, ob Du die relevanten Kompetenzen bereits hast.

Dieser Artikel baut auf der Kann-Liste des Artikels Grundlagen UML-Klassendiagramm auf.

Als Grundlagen zu Klassenbeziehungen kann ich nach Durchlesen des Artikels…

  • … erklären, wann Objekte in einer Assoziation zueinander stehen, und Assoziationen mit Namen, Leserichtung und Rollennamen notieren.

  • … an der Navigierbarkeit (gerichtete Assoziation) erkennen, welches Objekt welches kennt.

  • … Multiplizitäten (1, 0..1, *, 1..*, m..n) notieren, an der richtigen Seite lesen und in ganzen Sätzen erläutern.

  • … Aggregation und Komposition als Teil-Ganzes-Beziehungen beschreiben und anhand der Lebensdauer der Teile unterscheiden.

  • … begründet entscheiden, ob eine Beziehung als Assoziation, Aggregation oder Komposition modelliert werden sollte.

  • … Abhängigkeit, Assoziation, Aggregation, Komposition, Generalisierung und Realisierung an ihrer Notation erkennen und ihre Bedeutung erläutern.

  • … aus einem Anforderungstext ein Klassendiagramm mit allen Beziehungen und Multiplizitäten erstellen sowie ein vorgegebenes Diagramm ergänzen und Fehler darin korrigieren.

Darüber hinaus kann ich als Expertenwissen zu Klassenbeziehungen…

  • … erläutern, wie Assoziation, Aggregation und Komposition im Quelltext umgesetzt werden, und am Quelltext erkennen, welche Beziehung vorliegt.

  • … die Begriffe Kardinalität und Multiplizität unterscheiden und Objektkonstellationen gegen die Multiplizitäten eines Klassendiagramms prüfen.

  • … die Beziehungen in Entwurfsmustern wie dem Beobachter (Observer) erkennen und begründen, warum Beziehungen zu Interfaces die Kopplung verringern.

Das Klassendiagramm eines kleinen Abrechnungssystems zeigt, wohin die Reise geht: Am Ende dieses Artikels kannst Du Assoziation, Aggregation und Komposition darin lesen und begründen.

Überblick: Klassendiagramm mit Assoziation zwischen Kunde und Rechnung, Komposition zwischen Rechnung und Rechnungsposition und Aggregation zwischen Kunde und Konto (mit KI erstellt)

In der Objektorientierung können Klassen oder deren Objekte in Beziehung zueinander stehen. Klassen stehen beispielsweise bei der Vererbung miteinander in Beziehung und teilen sich so eine gemeinsame Struktur. Doch auch die einzelnen Instanzen der Klassen (Objekte) können Beziehungen zueinander haben: je nach Stärke und Art der Beziehung sprechen wir von Abhängigkeiten, Assoziationen, Aggregationen oder Kompositionen. Wir nähern uns den Objektbeziehungen schrittweise:

Abhängigkeit

Eine Abhängigkeit (Dependency) stellt in der UML die allgemeinste Form einer Beziehung zwischen zwei Elementen dar. Mit “Element” können hier Klassen oder Objekte gemeint sein. Man unterscheidet ein unabhängiges Element (Supplier) und ein von diesem abhängiges Element (Client).

Die Abhängigkeit einer Client-Klasse von einer Supplier-Klasse kann strukturell (den Aufbau betreffend) oder semantisch (die Bedeutung betreffend) begründet sein. Sie kann die Klassen selbst oder deren Objekte betreffen. Allen gemein ist, dass eine Veränderung des Suppliers Einfluss auf den Client haben kann.

Beispiel: Ein Kundenobjekt benötigt in seiner eigenen Methode bezahleRechnung(...) ein Rechnungsobjekt als Parameter, und ruft auf diesem eine Methode (setBezahlt()) auf. Kunde benötigt also die Klasse Rechnung in der Implementierung. Ändert sich die Implementierung oder Struktur von Rechnung, so hat das Einfluss auf Kunde:

Abhängigkeit zwischen Kunde und Rechnung

Abhängigkeiten können unterschiedlichster Natur sein: Client-Objekte können beispielsweise Methoden der Supplier-Objekte aufrufen (<<call>>, s.o.), deren Objekte erzeugen (<<create>>) oder sie ganz allgemein nutzen (<<use>>). Abhängigkeiten gibt es auch auf Klassenebene, <<substitute>> beschreibt beispielsweise, dass ein Element ein anderes ersetzt. Die UML kennt eine Vielzahl weiterer Dependency-Arten, die alle als Stereotyp mit den doppelten spitzen Klammern (Guillemets) notiert werden. Im UML-Standard finden sich Dependencies im Kapitel 7.7..

Aufgrund der Vielzahl an Dependencies ist deren vollständige Modellierung in der Regel nicht sinnvoll. Man beschränkt sich daher häufig in UML-Diagrammen auf die Darstellung der nun folgenden Objektbeziehungen: Assoziation, Aggregation und Komposition.

Assoziation

Wenn Objekte zweier Klassen strukturell miteinander verbunden sind – ein Objekt das andere also dauerhaft kennt und darüber z. B. dessen Methoden aufrufen kann –, so nennt man diese Beziehung eine Assoziation (UML Spec 11.5). Die konkreten Verbindungen zwischen den Objekten heißen Links: Ein Link ist ein Tupel aus je einer Instanz der beteiligten Klassen (UML 2.5.1, Kap. 11.5.3). Beide Objekte arbeiten für ein gemeinsames Ziel zusammen. Die Beziehungen werden im UML Klassendiagramm durch eine Linie zwischen den Objekten dargestellt:

Unspezifische Assoziation zwischen Kunde und Rechnung: Rechnung kann Kundenattribut sein und Kunde Rechnungsattribut

Das gemeinsame Ziel der beteiligten Objekte wird oft anhand des Assoziationsnamens klar. Phrasen wie “benutzt ein”, “ist zugeordnet zu” oder “hat eine Beziehung zu” können diese Assoziationen recht unkonkret beschreiben, häufig finden sich präzisere Namen der Beziehung. Diese Assoziationsnamen werden auf der Assoziationskante mit Pfeil in Leserichtung angegeben: ein/e Kund*in bezahlt eine Rechnung.

Assoziation mit Name und Leserichtung: ein Kunde bezahlt eine Rechnung

Assoziationen stellen eine alternative Darstellung von Attributen dar: eines der Objekte ist ein Member (Attribut) des anderen Objekts. Wenn Assoziationen als einfache Linien dargestellt werden, ist nicht eindeutig festgelegt, welches Objekt ein Attribut des anderen ist (Kunde ein Attribut von Rechnung, Rechnung ein Attribut von Kunde, oder beides). Mit einer unspezifischen Assoziation kann ich mir dieses Implementierungsdetail also bewusst offen halten.

Keine Assoziation ist dagegen eine Zusammenarbeit, die nur für die Dauer eines Methodenaufrufs besteht. Das zeigt das folgende Beispiel: Wenn die Rechnung bezahlt ist, haben Kund*in und Rechnung keine weitere Beziehung zueinander:

Eine Kund*in bezahlt eine Rechnung: konkretere Darstellung

Das Ziel der Zusammenarbeit ist das Bezahlen einer Rechnung. Dazu erhält ein Kundenobjekt bei Aufruf der Methode bezahleRechnung() ein Rechnungsobjekt übergeben. Die Kund*in nutzt die Rechnung-Methoden getRechnungsbetrag() und setBezahlt(), um die Rechnung von ihrem vermoegen zu bezahlen. Nach Abschluss dieser Transaktion hält der Kunde keine Referenz mehr auf die Rechnung - beide Objekte können unabhängig voneinander fortbestehen.

Weil hier keine dauerhafte Verbindung zwischen den Objekten (kein Link) entsteht, sondern Rechnung nur als Parameter genutzt wird, ist diese Beziehung keine Assoziation, sondern eine Abhängigkeit: Sie wird als <<call>>- oder <<use>>-Dependency notiert, wie im Abschnitt Abhängigkeit gezeigt – darauf weist auch die Notiz im Diagramm oben hin. Das gilt immer, wenn ein Objekt nur als Parameter, Rückgabewert oder lokale Variable innerhalb des anderen verwendet wird. Eine Assoziation liegt erst vor, wenn ein Objekt das andere dauerhaft kennt, in der Regel über ein Referenzattribut (siehe Tabelle „Woran man die Beziehung im Quelltext erkennt“ und UML Spec 11.5: Assoziation).

Gerichtete Assoziation

Bei den bisherigen Darstellungen wurde im UML-Diagramm offengelassen, ob beide Objekte einander kennen. Beide Enden der Assoziationskante waren unspezifiziert.

Wenn genauer festgelegt werden soll, welches Objekt vom anderen weiß - also Zugriff auf eine Referenz hat - kann dies mit Kantenenden spezifisch dargestellt werden:

Unidirektional navigierbare Assoziationen

unidirektionale Navigation von Kunde zu Rechnung

Ein Kunde kann auf die Rechnung zugreifen (Pfeil in Richtung Rechnung), eine Rechnung weiß jedoch nicht, welche Kund*in sie bezahlt hat (Kreuz auf der Kantenseite Kunde). Eine Rechnung hält also keine Referenz (als Attribut) auf Kunde. Das wird v.a. auch im Beispielcode deutlich:

package de.oerinformatik.crm;

public class Rechnung {
    private double rechnungsbetrag;
    private boolean bezahlt;

    public double getRechnungsbetrag(){
        return rechnungsbetrag;
    }

    public void setRechnungsbetrag(double rechnungsbetrag){
        this.rechnungsbetrag = rechnungsbetrag;
    }
    
    public void setBezahlt(boolean istBezahlt){
        bezahlt = istBezahlt;
    }
}
package de.oerinformatik.crm;

public class Kunde {
    private double vermoegen;
    private Rechnung rechnung;

    public void bezahleRechnung(){
        vermoegen -= rechnung.getRechnungsbetrag();
        rechnung.setBezahlt(true);
    }
    Kunde(double vermoegen){
        this.vermoegen = vermoegen;
    }
}

Da diese Assoziation nur in einer Richtung navigiert werden kann, spricht man von einer unidirektional navigierbaren Assoziation.

Bidirektional navigierbare Assoziation

Wird beispielsweise beim Bezahlvorgang aufseiten der Rechnung in einem Attribut gespeichert, welche Kund*in die Rechnung bezahlt hat (z.B. in der Methode setBezahlt(istBezahlt:boolean, kunde:Kunde)), so kennen sich beide Objekte und halten Referenzen (als Attribut) auf das jeweils andere. Die Assoziation kann in beide Richtungen navigiert werden (Kunde ruft Methoden von Rechnung auf und umgekehrt). Wir sprechen dann von einer bidirektional navigierbaren Assoziation. In der UML wird dies durch zwei Pfeilenden an der Assoziationskante gekennzeichnet:

Kunde kennt Rechnung, Rechnung kennt Kunde

Im Beispielcode wird der gegenseitige Methodenaufruf der beiden Klassen deutlich:

public class Rechnung {
    private double rechnungsbetrag;
    public double getRechnungsbetrag() {return rechnungsbetrag;}

    private boolean bezahlt=false;
    private Kunde bezahltVon;
    public void setBezahlt(boolean bezahlt, Kunde kunde) {
        this.bezahlt = bezahlt;
        this.bezahltVon = kunde;
        System.out.println("wurde gezahlt von "+bezahltVon.toString());
}   }

public class Kunde {
    private double vermoegen;
    private Rechnung rechnung;
    
    public void bezahleRechnung(){
        vermoegen -= rechnung.getRechnungsbetrag();
        rechnung.setBezahlt(true, this);
    }   }

Nicht navigierbare Assoziation

Modellierbar ist auch der Fall, dass keine Richtung navigierbar ist (zwei “x” an den Kantenenden). Die UML 2.5.1 lässt das ausdrücklich zu, denn Navigierbarkeit ist optional (Kap. 11.5.4): Die Assoziation hält fest, dass Objekte beider Klassen über Links zusammengehören, aber keines der Objekte hält eine eigene Referenz auf das andere. Sinnvoll ist das, wenn die Beziehung nur als Modellwissen dokumentiert wird oder an anderer Stelle ausgewertet wird – etwa über eine Assoziationsklasse oder eine Abfrage, z. B. eine Zuordnungstabelle in der Datenbank, die ermittelt, welche Kund*in welche Rechnung bezahlt hat. Im Quelltext der beiden Klassen taucht dann kein Referenzattribut auf.

Ist nach der Bedeutung einer Assoziation gefragt, gehören zwei Dinge in die Antwort: Die Objekte der beiden Klassen stehen dauerhaft in Beziehung und kennen sich, und – falls Pfeilspitzen eingezeichnet sind – in welcher Richtung die Assoziation navigierbar ist. Ein Satz wie „Eine Bestellposition kennt ihren Artikel, ein Artikel kennt seine Bestellpositionen nicht“ beschreibt eine unidirektional navigierbare Assoziation vollständig. Fehlen Pfeile und Kreuze, ist die Navigierbarkeit nicht festgelegt – das ist kein Fehler, sondern eine bewusst offene Entscheidung.

Multiplizitäten

Bei den bisherigen Notationsmitteln für Assoziationen wurde noch keine Festlegung getroffen, wie viele Objekte der einen Klasse mit wie vielen Objekten der anderen Klasse in Beziehung stehen. Im folgenden Diagramm sind eine Reihe von Festlegungen für ein Programm zur Erstellung von Rechnungen getroffen. Zu jeder Kante können zwei unterschiedliche Multiplizitäten ausgewiesen werden: für jede der beiden Klassen je eine:

Rechnung, Rechnungsanschrift, Lieferanschrift, Rechnungsposition und Steuersatz

Sofern die Multiplizität die Zahl 1 überschreitet, werden die entsprechenden Referenzen in Objektsammlungen gespeichert. Je nach Programmiersprache können diese als Array, ArrayList, List o.ä. umgesetzt werden. Jede Multiplizität legt fest, wie viele Instanzen der Klasse, an der sie notiert ist, an der Beziehung mindestens und höchstens beteiligt sind. Möglich sind folgende Notationen:

UML-Notation
am Kantenende
Bedeutung Beispiel
n oder
n..n

(n ist positive Ganzzahl)
feste Anzahl:
Beziehung zu genau n Instanzen
Auf jeder Rechnung wird genau eine Lieferanschrift genannt; Jede Rechnungsposition ist genau einer Rechnung zugeordnet. Da hier Unter- und Obergrenze identisch sind (z.B. 3..3) kann eine Grenze weggelassen werden (3).
0..1 optional:
Beziehung zu keiner oder einer Instanz
Eine Rechnungsanschrift ist optional. Eine Rechnung kann eine gesonderte Rechnungsanschrift haben (andernfalls ist sie identisch mit der Lieferanschrift).
m..n

(n und m sind Ganzzahlen, 0 <= m < n)
Beziehungen zwischen m und n unterschiedlichen Instanzen Es gibt genau zwei Steuersätze (ermäßigt/normal). Auf jeder Rechnung wird mindestens ein Steuersatz ausgewiesen, höchstens aber beide.
* oder
0..*
null oder mehr
Beziehung zu beliebig vielen Instanzen (oder zu keiner)
Ein Steuersatz kann auf beliebig vielen Rechnungen ausgewiesen sein. Denkbar auch, dass er auf keiner Rechnung ausgewiesen wird. Anstelle von 0..* kann auch verkürzt * notiert werden.
n..*

(n ist positive Ganzzahl)
mindestens n oder mehr Auf jeder Rechnung findet sich mindestens eine Rechnungsposition.

Im Programmtext muss anhand des Datentyps der Referenz oder über Implementierung sichergestellt werden, dass die jeweilige Anzahl an Instanzen übergeben werden kann.

Multiplizitäten richtig lesen

Eine Multiplizität steht immer an der Klasse, deren Anzahl sie angibt – also auf der Seite, die der lesenden Klasse gegenüberliegt. Am sichersten ist es, jede Beziehung in zwei Sätzen auszusprechen:

  • „Eine Rechnung hat mindestens eine Rechnungsposition.“ (Multiplizität 1..* steht an Rechnungsposition.)

  • „Eine Rechnungsposition gehört zu genau einer Rechnung.“ (Multiplizität 1 steht an Rechnung.)

So lassen sich Multiplizitäten verständlich erläutern: Man nennt die Untergrenze („mindestens …“ bzw. „keine oder …“) und die Obergrenze („höchstens …“ bzw. „beliebig viele“) und sagt, aus wessen Sicht man liest. Ein häufiger Fehler ist das Vertauschen der beiden Enden – dann hätte im Beispiel jede Rechnungsposition mehrere Rechnungen.

Nicht jede Regel lässt sich mit Multiplizitäten ausdrücken. „Je Zeitslot darf eine Person höchstens eine Session buchen“ betrifft drei Klassen gleichzeitig; solche Regeln notiert man als Einschränkung (Constraint) in geschweiften Klammern, z. B. in einer Notiz {höchstens eine Buchung je Slot}.

Rollennamen, mehrere Beziehungen und Selbstbeziehungen

Zwischen zwei Klassen kann es mehrere Assoziationen mit unterschiedlicher Bedeutung geben. Damit man sie unterscheiden kann, schreibt man an die Enden Rollennamen: Sie sagen, welche Rolle die Objekte am jeweiligen Ende spielen. Im Quelltext werden aus Rollennamen meist die Namen der Referenzattribute. Eine Klasse kann auch mit sich selbst in Beziehung stehen (reflexive Assoziation oder Selbstbeziehung) – auch dann helfen Rollennamen beim Lesen:

Mitarbeiter leiten Projekte und arbeiten in Projekten mit; ein Mitarbeiter kann Vorgesetzte*r anderer Mitarbeiter sein (mit KI erstellt)

Gelesen: Ein Projekt hat genau eine leitung und mindestens ein Mitglied; ein Mitarbeiter leitet beliebig viele Projekte und arbeitet in beliebig vielen mit. Ein Mitarbeiter hat höchstens eine vorgesetzte Person und beliebig viele Teammitglieder.

Viele-zu-viele-Beziehungen

Anders als im relationalen Datenbankmodell braucht eine m:n-Beziehung im Klassendiagramm keine Zwischenklasse: An beide Enden schreibt man * (bzw. 0..* oder 1..*), und im Quelltext hält jedes Objekt eine Sammlung von Referenzen auf die anderen. Erst wenn die Beziehung selbst Eigenschaften hat (z. B. das Datum einer Buchung), lohnt sich eine eigene Klasse oder eine Assoziationsklasse.

Die Begriffe Kardinalität und Multiplizität

In der UML wird eine tatsächliche Anzahl der verknüpften Instanzen Kardinalität genannt. An folgendem Beispiel soll das deutlich werden: Ein Fahrzeug kann eines oder viele Räder haben.

Ein Fahrzeug hat ein oder mehrere Räder (Multiplizität 1..*)

Ist das Fahrzeug ein Fahrrad, so beträgt die tatsächliche Anzahl (die Kardinalität) 2, bei einem Auto 4, bei einem Einrad 1, bei einer Ape 3 und bei einem Zug ein Vielfaches von 4 - z.B. 128. Der Begriff Kardinalität beschreibt in der UML also die konkrete Anzahl an Beziehungen einer identifizierten Instanz der Klasse. Das weicht von der Bedeutung ab, mit der Kardinalität bei der Datenbankmodellierung (Entity Relationship Model) verwendet wird - dort ist Kardinalität synonym zu Multiplizität zu sehen. Ist im Zusammenhang mit einem Klassendiagramm von Kardinalitäten die Rede, sind deshalb meist die Multiplizitäten gemeint.

In der UML ist der Begriff Multiplizität definiert als die Menge aller zulässigen Kardinalitäten. Ein Fahrzeug allgemein kann ein oder viele Räder haben: Die Multiplizität ist daher 1..*. Ob eine konkrete Objektkonstellation zulässig ist, prüft man, indem man für jedes Objekt die Kardinalität (Zahl seiner Verbindungen) mit der Multiplizität im Klassendiagramm vergleicht – das geht besonders gut mit einem UML-Objektdiagramm.

Aggregation

Assoziationen beschreiben eine allgemeine, einem Ziel zugeordnete Zusammenarbeit zweier Objekte. Wir können diese mit “benutzt ein” beschreiben. Eine engere Bindung zweier Objekte ist gegeben, wenn Objekte zueinander eine dauerhafte Teil-Ganzes-Beziehung haben, die mit Phrasen wie “besteht aus” oder “hat ein/e” beschrieben werden können (in umgekehrter Leserichtung: “ist Teil von”).

Die zugeordneten Instanzen der Teile werden in Attributen des Ganzen verwaltet. Per Setter-Methoden oder im Konstruktor wird das Ganze (das Aggregat) zusammengesetzt, somit im wörtlichen Sinne aggregiert. Man nennt diese Beziehung daher Aggregation. Im UML-Standard wird sie im Kapitel 9.5.3 beschrieben (etwas versteckt auf der Folgeseite, vor einer Tabelle).

Im UML-Klassendiagramm wird diese besondere Assoziation durch eine nicht ausgefüllte Raute aufseiten des Ganzen notiert.

Ein Konto ist Teil des Objekts Kunde

Bei einer Aggregation kann das Teil auch unabhängig vom Ganzen existieren - es gibt Referenzen auf das Teil außerhalb des Ganzen (z.B. in dem die Teil-Instanz außerhalb des Ganzen erzeugt wird).

Die UML-Spezifikation lässt die genaue Bedeutung der Aggregation (shared aggregation) bewusst offen: Sie hängt vom Anwendungsbereich ab. In der Praxis gilt meist: Die Aggregation ist eine Teil-Ganzes-Beziehung, bei der die Lebensdauer der Teile nicht an das Ganze gebunden ist. Wird das Ganze gelöscht, bleiben die Teile erhalten.

Es kann auch Teilinstanzen geben, die mehreren Ganzen zugeordnet sind. Denkbar wäre im obigen Beispiel etwa, dass Konten mehreren Kund*innen zugeordnet werden oder eine Kund*in gelöscht wird, die Konten aber weiterbestehen. Ein Quelltextbeispiel:

public class Kunde {
    private ArrayList<Konto> kontenListe = new ArrayList<>();
    public void addKonto(Konto konto){this.kontenListe.add(konto);}

    public double gesamtVermoegen(){
        double vermoegen = 0;
        for(Konto konto:kontenListe){
            vermoegen+=konto.getKontostand();
        }
        return vermoegen;
}   }

public class Konto {
    private double kontostand;
    public double getKontostand() {return kontostand;}
}

Komposition

Bei der Komposition handelt es sich um eine Sonderform der Teil/Ganzes-Beziehung: Die Teilobjekte existieren nur innerhalb des Ganzen und sind somit in ihrer Lebensdauer auf die Lebensdauer des zugehörigen Ganzen beschränkt. Da dies eine festere Bindung zwischen Teil und Ganzem ist, wird im UML-Standard (Kapitel 9.5.3) auch von einer “starken Form der Aggregation” gesprochen.

Aufgrund dieser Abhängigkeit kann ein Teil auch nur mit einem Ganzen in Beziehung stehen - die Multiplizität aufseiten des Ganzen ist somit “1” (der Defaultwert) und wird daher oft weggelassen. Genau genommen verlangt die UML am Ganzen eine Obergrenze von 1, also 1 oder 0..1. Mit 0..1 darf ein Teil zeitweise ohne Ganzes existieren (siehe „Für Experten“). Steht am Ganzen dagegen * oder 1..*, kann es keine Komposition sein.

Die Komposition wird mit einer ausgefüllten Raute aufseiten des Ganzen gekennzeichnet:

Eine Rechnungsposition ist existenziell abhängig von einer Rechnung

Kompositionen erkennt man in der Programmierung in der Regel daran, dass das Teil innerhalb des Ganzen erzeugt wird und das Teilobjekt nicht über Getter oder öffentliche Attribute nach außen veröffentlicht wird. Nur das Ganze hält Referenzen auf das Teil.

Die Entscheidung, ob eine Beziehung als Aggregation oder Komposition umgesetzt wird, trifft die Person, die programmiert. Häufig gibt die Fachdomäne über gegebene Abhängigkeiten bereits Hinweise, was sinnvoll ist. In der Regel führt die Komposition zu besser wartbarem Code, da weniger externe Abhängigkeiten möglich sind.

Quelltextbeispiel:

public class Rechnung {

   private ArrayList<Rechnungsposition> rechnungspositionen = new ArrayList<Rechnungsposition>();

   public void addRechnungsposition(String name, String artikelnummer, Integer anzahl, double nettopreis) {
       rechnungspositionen.add(new Rechnungsposition(name, artikelnummer, anzahl, nettopreis));
   }

   @Override
   public String toString() {
       String text = "Rechnung: \n";
       for (Rechnungsposition position : rechnungspositionen) {
           text += position.toString() + "\n";
       }
       return text;
}   }


class Rechnungsposition {

   private String name;
   private String artikelnummer;
   private Integer anzahl;
   private double nettopreis;

   Rechnungsposition(String name, String artikelnummer, Integer anzahl, double nettopreis) {
       this.name = name;
       this.artikelnummer = artikelnummer;
       this.anzahl = anzahl;
       this.nettopreis = nettopreis;
   }

   @Override
   public String toString() {
       return "Name: " + this.name + " /  Artikelnummer: " + artikelnummer + " / Anzahl: " + this.anzahl + " / Nettoeinzelpreis: " + this.nettopreis;
}    }

Für Experten / Hintergrund

Die UML lässt die Möglichkeit, dass Teile vom Ganzen entkoppelt werden und dann auch nicht mit dem Ganzen gelöscht werden. Um diesen Sonderfall abzubilden, müsste man eine Methode implementieren, die das Teil zurückgibt und innerhalb des Ganzen die Referenz auf das Teil löscht, sobald es das Ganze verlässt. In obigem Beispiel könnte so eine Methode in Rechnung etwa so aussehen:

    public Rechnungsposition removeRechnungsposition(int index) {
         return rechnungspositionen.remove(index);
    }

Aggregation oder Komposition? Entscheiden und begründen

Ob eine Teil-Ganzes-Beziehung als Aggregation oder als Komposition modelliert wird, ist eine Entwurfsentscheidung. Sie sollte immer begründet werden, denn beide Beziehungsarten sind Teil-Ganzes-Beziehungen und unterscheiden sich nur in der Lebensdauer und Zugehörigkeit der Teile. Diese Fragen helfen:

Entscheidungsfragen für Aggregation und Komposition
Frage Aggregation Komposition
Ist es überhaupt eine Teil-Ganzes-Beziehung („besteht aus“, „hat“)? ja ja
Existiert das Teil vor dem Ganzen oder nach dessen Löschen weiter? ja, möglich nein, Lebensdauer an das Ganze gebunden
Kann ein Teil gleichzeitig zu mehreren Ganzen gehören? ja, möglich nein, höchstens zu einem
Kann ein Teil von einem Ganzen zu einem anderen wechseln? ja nur, wenn es vorher herausgelöst wird
Multiplizität am Ganzen beliebig (z. B. 0..*) 1 (oder 0..1)

Eine gute Begründung nennt immer die Lebensdauer: „Wird die Rechnung gelöscht, werden auch ihre Positionen gelöscht; eine Position kann ohne Rechnung nicht existieren – daher Komposition.“ Oder: „Eine Spielerin bleibt erhalten, wenn sie die Mannschaft wechselt, und kann gleichzeitig in Verein und Nationalteam spielen – daher Aggregation und keine Komposition.“

Woran man die Beziehung im Quelltext erkennt

Klassenbeziehungen und ihre Umsetzung im Quelltext
Beziehung typische Umsetzung
Assoziation Referenzattribut auf das andere Objekt (bei Obergrenze größer 1 eine Sammlung wie ArrayList); Rollenname wird Attributname
Aggregation Ganzes hält eine Sammlung von Teilen; die Teile werden außerhalb erzeugt und z. B. über add…() oder den Konstruktor übergeben; andere Objekte dürfen sie ebenfalls referenzieren
Komposition Ganzes erzeugt seine Teile selbst (new im Ganzen) und gibt keine Referenzen nach außen; endet die Lebensdauer des Ganzen, sind auch die Teile nicht mehr erreichbar
Abhängigkeit Objekt wird nur als Parameter, Rückgabewert oder lokale Variable genutzt, nicht dauerhaft gespeichert

In Java oder Python werden Objekte nicht ausdrücklich gelöscht: Ein Objekt wird vom Garbage Collector entfernt, sobald es nicht mehr erreichbar ist. Bei einer Komposition sind die Teile nur über das Ganze erreichbar und verschwinden mit ihm; bei einer Aggregation halten andere Programmteile oft noch Referenzen auf die Teile. In C++ muss das Ganze seine Teile im Destruktor selbst freigeben.

Im Klassendiagramm werden die Referenzattribute zu Assoziationen meist nicht zusätzlich als Attribut eingetragen, weil die Linie dieselbe Information trägt. Viele Beispiellösungen zeigen sie trotzdem (z. B. -positionen: Rechnungsposition[1..*]); beides wird in der Regel akzeptiert.

Übersicht von Assoziation, Aggregation und Komposition

Die unterschiedlichen Objektbeziehungen anhand der oben genannten Beispiele ergeben insgesamt die Modellierung eines Abrechnungssystems:

Die unterschiedlichen Objektbeziehungen zwischen Konto, Kunde, Rechnung und Rechnungsposition als UML-Klassendiagramm

Alle Beziehungsarten im Vergleich

In Aufgaben soll oft die „Art der Beziehung“ zwischen zwei Klassen erläutert werden. Neben den Objektbeziehungen aus diesem Artikel kommen dabei auch die Klassenbeziehungen Generalisierung (Vererbung) und Realisierung (Interface) vor. Entscheidend sind Linienart und Linienende:

Übersicht der Beziehungsarten: Abhängigkeit, Assoziation, gerichtete Assoziation, Aggregation, Komposition, Generalisierung und Realisierung (mit KI erstellt)
Beziehungsarten im UML-Klassendiagramm
Beziehung Notation Bedeutung (Kurzform für Antworten)
Abhängigkeit gestrichelt, offene Pfeilspitze, oft mit Stereotyp <<use>> Eine Klasse benutzt eine andere nur kurzzeitig (Parameter, lokale Variable); ändert sich die benutzte Klasse, kann das die benutzende betreffen.
Assoziation durchgezogene Linie, ggf. Name mit Leserichtung, Rollennamen, Multiplizitäten Objekte stehen in Beziehung und kennen sich.
gerichtete Assoziation durchgezogen mit offener Pfeilspitze (ggf. Kreuz am anderen Ende) Nur in Pfeilrichtung navigierbar: Nur ein Objekt kennt das andere.
Aggregation hohle Raute am Ganzen Teil-Ganzes-Beziehung; Teile können unabhängig vom Ganzen existieren und zu mehreren Ganzen gehören.
Komposition gefüllte Raute am Ganzen Teil-Ganzes-Beziehung mit existenzabhängigen Teilen; ein Teil gehört zu genau einem Ganzen und wird mit ihm gelöscht.
Generalisierung durchgezogen, hohles Dreieck an der allgemeineren Klasse Die Unterklasse erbt Attribute und Methoden („ist ein“) und kann Methoden überschreiben.
Realisierung gestrichelt, hohles Dreieck am Interface Die Klasse implementiert alle abstrakten Methoden des Interfaces und kann überall dort eingesetzt werden, wo das Interface erwartet wird.

Typische Fehler beim Zeichnen und Lesen:

  • Die Raute sitzt am Teil statt am Ganzen.

  • Die Multiplizitäten sind vertauscht (siehe „Multiplizitäten richtig lesen“).

  • Ein Teil ist per Komposition an zwei verschiedene Ganze gebunden – eine Komposition erlaubt nur ein Ganzes.

  • Eine Klasse „erbt“ mit durchgezogener Linie von einem Interface, statt es mit gestrichelter Linie zu realisieren.

  • Für eine reine Benutzung (Parameter) wird eine dauerhafte Assoziation gezeichnet.

Beziehungen in Entwurfsmustern erkennen

Entwurfsmuster lassen sich im Klassendiagramm an ihren typischen Beziehungen erkennen. Diese folgen dabei immer derselben Idee: Klassen kennen sich möglichst nur über Interfaces oder abstrakte Klassen.

Beobachter-Muster: Subjekt aggregiert beliebig viele Beobachter, Wetterstation erbt von Subjekt, Anzeigetafel und Protokoll realisieren das Interface Beobachter (mit KI erstellt)
  • Beobachter (Observer): Das Subjekt verwaltet eine Sammlung von Beobachtern (Aggregation zum Interface Beobachter, Multiplizität 0..*), die sich an- und abmelden. Die konkreten Beobachter realisieren das Interface und implementieren aktualisieren(). Die Beobachter existieren unabhängig vom Subjekt – daher Aggregation, nicht Komposition. Weil das Subjekt nur das Interface kennt, lassen sich neue Beobachter ergänzen, ohne das Subjekt zu ändern (lose Kopplung).

  • Strategie (Strategy): Eine Klasse hält eine Referenz auf ein Strategie-Interface (Assoziation, Aggregation oder – wenn die Strategie im Objekt erzeugt wird und nur ihm gehört – Komposition); mehrere konkrete Strategien realisieren das Interface.

  • Stellvertreter (Proxy): Stellvertreter und echtes Objekt realisieren dasselbe Interface; der Stellvertreter hält eine Referenz auf das echte Objekt und leitet Aufrufe weiter.

Mehr zu den Mustern selbst steht in den Artikeln zu den Entwurfsmustern.

Das ganze Beispiel als Java-Code

Wer versucht hat, das ganze per UML geplante OOP-Programm in Java nachzuvollziehen, sollte etwa diesen Quelltext am Ende vor sich haben und ausführen können. Alle Klassen aus den vergangenen UML-Modellierungsbeispielen liegen als Java-Dateien im Repository (Ordner src/java/assoziation):

Die Ordner entsprechen den Paketen (de/oerinformatik/crm, de/oerinformatik/abrechnung). Im Ordner src/java/assoziation lässt sich das Programm mit javac -d out de/oerinformatik/*/*.java übersetzen und mit java -cp out de.oerinformatik.crm.Investmentrechner starten.

Nächster Schritt: Klassenbeziehungen

Wir haben jetzt die Beziehungen behandelt, die konkrete Instanzen (also Objekte) untereinander haben können. Im folgenden Schritt soll es darum gehen, dass wir Verhalten und Strukturen, die in Klassen definiert sind, an andere Klassen vererben können: es geht also um Klassenbeziehungen (Vererbung).

Leitfragen

  1. Woran erkennst Du, ob zwei Klassen in einer Assoziation, einer Aggregation oder einer Komposition zueinander stehen, und wie notierst Du die drei Beziehungen?

Eine Assoziation liegt vor, wenn Objekte dauerhaft verbunden sind und sich kennen (meist über ein Referenzattribut; eine reine Parameterübergabe ist dagegen eine Abhängigkeit); sie wird als durchgezogene Linie notiert, ggf. mit Name, Leserichtung und Pfeilspitzen für die Navigierbarkeit. Aggregation und Komposition sind Teil-Ganzes-Beziehungen („besteht aus“, „hat“): Bei der Aggregation können die Teile unabhängig vom Ganzen existieren (hohle Raute am Ganzen), bei der Komposition ist ihre Lebensdauer an das Ganze gebunden (gefüllte Raute am Ganzen) – siehe Abschnitt „Assoziation“ und Abschnitt „Übersicht von Assoziation, Aggregation und Komposition“.

  1. Wie liest Du die Multiplizitäten an beiden Enden einer Beziehung, und wie formulierst Du sie als Sätze?

Eine Multiplizität steht immer an der Klasse, deren Anzahl sie angibt, also auf der Seite gegenüber der Klasse, aus deren Sicht Du liest. Sprich jede Beziehung in zwei Sätzen mit Unter- und Obergrenze aus, z. B. „Eine Rechnung hat mindestens eine Rechnungsposition“ (1..* an Rechnungsposition) und „Eine Rechnungsposition gehört zu genau einer Rechnung“ (1 an Rechnung) – siehe Abschnitt „Multiplizitäten richtig lesen“.

  1. Was geschieht mit den Teilen, wenn das Ganze gelöscht wird – bei einer Aggregation und bei einer Komposition?

Bei einer Aggregation bleiben die Teile erhalten, wenn das Ganze gelöscht wird, denn ihre Lebensdauer ist nicht an das Ganze gebunden. Bei einer Komposition werden die Teile mit dem Ganzen gelöscht – es sei denn, ein Teil wurde vorher ausdrücklich herausgelöst – siehe Abschnitt „Aggregation“ und Abschnitt „Komposition“.

  1. Mit welchen Argumenten begründest Du, ob eine Beziehung als Aggregation oder als Komposition modelliert werden sollte?

Entscheidend ist die Lebensdauer: Existiert das Teil vor dem Ganzen oder nach dessen Löschen weiter, kann es gleichzeitig zu mehreren Ganzen gehören oder das Ganze wechseln, spricht das für eine Aggregation. Ist das Teil ohne das Ganze nicht sinnvoll, gehört es zu höchstens einem Ganzen und steht am Ganzen die Multiplizität 1 (oder 0..1), ist es eine Komposition – siehe Abschnitt „Aggregation oder Komposition? Entscheiden und begründen“.

  1. Wozu dienen Rollennamen, und wie modellierst Du mehrere Beziehungen zwischen denselben Klassen oder eine Beziehung einer Klasse zu sich selbst?

Rollennamen an den Assoziationsenden sagen, welche Rolle die Objekte am jeweiligen Ende spielen, und werden im Quelltext meist zu Namen der Referenzattribute. Mehrere Beziehungen zwischen denselben Klassen zeichnest Du als getrennte Assoziationen mit unterschiedlichen Rollennamen (z. B. leitung und Mitglieder), eine Selbstbeziehung (reflexive Assoziation) als Linie von der Klasse zu sich selbst, ebenfalls mit Rollennamen wie vorgesetzte Person und Teammitglieder – siehe Abschnitt „Rollennamen, mehrere Beziehungen und Selbstbeziehungen“.

  1. Wie unterscheiden sich Abhängigkeit, Generalisierung und Realisierung von den Objektbeziehungen?

Eine Abhängigkeit (gestrichelte Linie mit offener Pfeilspitze, oft <<use>>) beschreibt nur eine kurzzeitige Nutzung als Parameter oder lokale Variable, keine dauerhafte Beziehung zwischen Objekten. Generalisierung (durchgezogen, hohles Dreieck) und Realisierung (gestrichelt, hohles Dreieck am Interface) sind Klassenbeziehungen: Die Unterklasse erbt („ist ein“) bzw. die Klasse implementiert die abstrakten Methoden eines Interfaces – siehe Abschnitt „Abhängigkeit“ und Abschnitt „Alle Beziehungsarten im Vergleich“.

  1. Woran erkennst Du im Quelltext, welche Beziehung umgesetzt wurde?

Eine Assoziation erkennst Du an einem Referenzattribut (bei Obergrenze größer 1 an einer Sammlung), eine Aggregation daran, dass das Ganze außerhalb erzeugte Teile z. B. über add…() oder den Konstruktor aufnimmt. Bei einer Komposition erzeugt das Ganze seine Teile selbst mit new und gibt keine Referenzen nach außen; bei einer Abhängigkeit wird das Objekt nur als Parameter, Rückgabewert oder lokale Variable genutzt – siehe Abschnitt „Woran man die Beziehung im Quelltext erkennt“.

  1. Welche Beziehungen kommen im Beobachter-Muster vor, und warum kennt das Subjekt nur das Interface der Beobachter?

Im Beobachter-Muster aggregiert das Subjekt beliebig viele Beobachter (Aggregation zum Interface Beobachter, Multiplizität 0..*), die konkreten Beobachter realisieren dieses Interface und ein konkretes Subjekt erbt ggf. vom Subjekt. Weil das Subjekt nur das Interface kennt, lassen sich neue Beobachter ergänzen, ohne das Subjekt zu ändern (lose Kopplung) – siehe Abschnitt „Beziehungen in Entwurfsmustern erkennen“.


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “UML-Klassendiagramm Objektbeziehungen - Assoziationen” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/uml-klassendiagramm-assoziation veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/uml/uml-diagramme. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 29.10.2026.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: