Klassen- und Implementationsdiagramm: Unterschied zwischen den Versionen
(46 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
[[Kategorie:Informatik]] | [[Kategorie:Informatik]] | ||
[[Kategorie:Informatik-EF]] | |||
[[Kategorie:Informatik-Q1]] | |||
[[Kategorie:Informatik-Abitur]] | [[Kategorie:Informatik-Abitur]] | ||
* '''Klassendiagramme''' sind wesentlicher Bestandteil der UML (=Unified Modeling Language). | * '''Klassendiagramme''' sind wesentlicher Bestandteil der UML (=Unified Modeling Language). | ||
* '''Implementationsdiagramme''' gibt es nur in Nordrhein-Westfalen! | * '''Implementationsdiagramme''' gibt es nur in Nordrhein-Westfalen! | ||
=Fachbegriffe= | |||
* Klasse, Objekt | |||
* hat-Beziehung, kennt, erbt von, ''"hat ein Attribut ... vom Typ List, das nur Objekte vom Typ... enthalten kann"'' | |||
* Attribut, Attribut-Typ | |||
* Methode, Parameter, Parameter-Typ, Rückgabe-Typ, öffentliche Methode, private Methode | |||
* get-Methode (=gibt nur ein Attribut zurück), set-Methode (=trägt nur einen neuen Wert in ein Attribut ein) | |||
* Geheimnisprinzip | |||
=Wofür braucht man Klassen- und Implementationsdiagramme?= | |||
Klassendiagramme braucht man, um Softwaresysteme zu '''modellieren'''. Dabei wird im Klassendiagramm folgendes festgelegt: | |||
* Name, Attribute (mit Typ) und Methoden (mit Parameter und Rückgabetyp) jeder einzelnen Klasse. | |||
* Die Beziehungen zwischen den Klassen. | |||
<u>Nicht</u> festgelegt wird im Klassendiagramm die konkrete Programmierung. | |||
Sehr vereinfacht sieht der Entwicklungsprozess so aus: <br/>Aus der ''Anforderungsermittlung'' (=einem Text, der mit dem Auftraggeber abgesprochen ist) zeichnet der ''Software-Architekt'' Klassendiagramme, die die gesamte in der Anforderungsermittlung beschriebene Funktionalität abbilden. In großen Systemen kann es mehrere hundert Klassen geben. <br/>Anschließend können die Programmierer die im Klassendiagramm beschriebenen Klassen implementieren (z.B. in Java). | |||
=Anforderungen an Implementationsdiagramme= | |||
''Die folgenden Anforderungen sind erst dann interessant, wenn man mehrere Klassen hat, die in Beziehung zueinander stehen!''<br/>''Was hier im folgende steht, ist nicht gedeckt durch Literatur etc. Es hat sich aber für den Unterricht, in der (einfachen) Praxis und auch im Zentralabitur als brauchbar erwiesen.'' | |||
Implementationsdiagramme sollen eine '''Software-Architektur für eine Software-Anwendung''' definieren.<br/>Deswegen gibt es zwei Grundanforderungen, die klar sind: | |||
* Die Anforderungen müssen mit der Software-Architektur möglichst einfach realisierbar sein. | |||
* Die Software-Architektur soll sich möglichst einfach implementieren lassen, d.h. in Quellcode übersetzen lassen. | |||
Daraus lassen sich folgende '''Anforderungen''' ableiten: | |||
'''Intuitiv verständlich'''<br/>Objektorientierung lebt davon, dass man mit ihrer Hilfe Szenarien aus der realen Welt möglichst "realitätsnah" modellieren und implementieren kann. Das sollte man nutzen, und deswegen sollten Implementationsdiagramme intuitiv verständlich sein. | |||
'''Geheimnisprinzip:'''<br/>Jede Klasse sollte die Daten, die sie verwaltet, privat halten und nur einen kontrollierten Zugriff darauf bieten. <br/>Beispiel: Die Klasse <code>Fahrkartenautomat</code> sollte auf keinen Fall das Attribut <code>eingeworfenesGeld</code> öffentlich machen! Wer weiß, was ein anderer Programmierer dann damit tut??! Stattdessen sollte es eine Methode <code>geldEinwerfen</code> geben, bei der der Fahrkartenautomat den Zugriff auf <code>eingeworfenesGeld</code> steuern kann. | |||
'''Möglichst Beziehungen nur in einer Richtung:'''<br/> | |||
Das erleichtert später die Implementierung! | |||
'''möglichst Top-Down:'''<br/> | |||
Streng Hierachische Architekturen sind in der Regel leicht beherrschbar. Die Beziehungen gehen dann in der Regel von oben nach unten. Wenn ganz an der Spitze eine Klasse steht, die "alles kontrolliert", kann diese Klasse Aufgaben an untergeordnete Klassen delegieren. | |||
=Vorgaben für das Zentralabitur= | =Vorgaben für das Zentralabitur= | ||
Zeile 21: | Zeile 63: | ||
# Zeile: die '''Attribute''' der Klasse | # Zeile: die '''Attribute''' der Klasse | ||
# Zeile: die '''Methoden''' der Klasse | # Zeile: die '''Methoden''' der Klasse | ||
## Dabei wird als erstes der '''Konstruktor''' aufgeführt. | |||
==Syntax innerhalb des Klassendiagramms== | |||
Klassendiagramme haben eine eigene Syntax, die (leider!) von der Java-Syntax abweicht: | |||
* + bedeutet <code>public</code> | |||
* - bedeutet <code>private</code> | |||
* '''Attribute''': | |||
** VOR dem Doppelpunkt: "+" bzw. "-" und der Attribut-'''Name''' | |||
** NACH dem Doppelpunkt: Attribut-'''Typ''' | |||
* '''Methoden''': | |||
** erst "+" bzw. "-" (für <code>public</code> bzw. <code>private</code>) | |||
** Methoden-Name | |||
** Parameter (in Klammern!): VOR dem Doppelpunkt der Parameter-'''Name''', NACH dem Doppelpunkt der Parameter-'''Typ'''. | |||
** NACH dem Doppelpunkt: Rückgabe-'''Typ''' der Methode | |||
==Java-Implementierung== | ==Java-Implementierung== | ||
Das oben gegebene Klassendiagramm wird jetzt in Java | Wie die einzelnen Klassen implementiert werden, das entscheidet der zuständige Programmierer; er muss sich aber <u>genau</u> an die Vorgaben des Klassendiagramms halten. | ||
Das oben gegebene einfache Klassendiagramm kann z.B. wie folgt in Java implementiert werden. | |||
<code> | |||
public class Buch{ | |||
//Attribute | |||
private String titel; | |||
private int regalNr; | |||
//Konstruktor | |||
public Buch(String pTitel){ | |||
titel = pTitel; | |||
} | |||
// get- und set-Methoden | |||
public int getRegalNr() { | |||
return regalNr; | |||
} | |||
public void setRegalNr(int pRegalNr) { | |||
regalNr = pRegalNr; | |||
} | |||
public String getTitel() { | |||
return titel; | |||
} | |||
} | |||
</code> | |||
=Beziehungen zwischen Klassen= | |||
[[File:Kennt-erbt-von.png|thumb|kennt, erbt von|236px]] | |||
Es gibt zwei Beziehungstypen: | |||
* '''Kennt'''-Beziehung ('''Assoziation'''): Ein Objekt der Klasse A kennt ein/mehrere Objekte der Klasse B.<br/>Beispiel: Fahrer '''kennt''' mehrere Tankstellen. | |||
* '''Vererbung''': Klasse A erbt von Klasse B. Man sagt auch oft: A '''ist ein''' B <br/>Beispiel: Roller '''erbt von''' Fahrzeug, bzw. Roller '''ist ein''' Fahrzeug. | |||
''Anmerkung:''<br/> | |||
''Im UML-Standard gibt es noch einen dritten Beziehungstyp:''<br/> | |||
''Hat-Beziehung: Ein Objekt der Klasse A hat (=besitzt!) ein/mehrere Objekte der Klasse B. <br/>Beispiel: Fahrer '''hat''' einen Roller.<br/> | |||
''Im Zentralabitur wird aber zwischen kennt-Beziehung und hat-Beziehung nicht unterschieden.'' | |||
==Multiplizitäten der Kennt-Beziehung== | |||
Multiplizitäten werden entweder genau oder mit einer Unter- und einer Obergrenze notiert.<br/> | |||
Beispiele: | |||
* '''1''': genau ein | |||
* '''0..1''': 0 oder ein | |||
* '''2..4''': mindestens 2 und höchstens 4 | |||
* '''1..*''': mindestens 1 (und höchstens beliebig viele) | |||
==Beispiel== | |||
[[File:Roller-fahrer-tankstelle.png|thumb|Beziehungen zwischen Roller, Fahrer und Tankstelle|475px]] | |||
Im Klassendiagramm rechts sind die Beziehungen zwischen Roller, Fahrer und Tankstelle dargestellt. (Attribute und Methoden der einzelnen Klassen sind hier nicht aufgeführt. | |||
'''Erläuterung:''' | |||
* Jeder Fahrer '''kennt genau einen (nämlich seinen)''' Roller. | |||
* Jeder Fahrer '''kennt mindestens eine, aber beliebig viele''' Tankstellen. | |||
=Erstellen von Klassendiagrammen= | |||
Klassendiagramme sind vor allem '''Planungswerkzeuge''' für die Entwicklung umfangreicher Software-Systeme. | |||
Mithilfe von Klassendiagrammen kann man festlegen, was programmiert werden muss. | |||
==Attribute, Konstruktor, Methoden== | |||
Folgende Fragestellungen helfen beim Erstellen von Klassendiagrammen: | |||
* <u>Attribute</u>: Welche Informationen müssen Objekte der Klasse speichern, damit sie im Szenario funktionieren können? | |||
* <u>Parameter des Konstruktors</u>: Welche Information muss man angeben, wenn man ein Objekt der Klasse erzeugt? | |||
* <u>Methoden</u>: Was kann man mit Objekten der Klasse tun? | |||
** <u>Parameter</u> der Methoden: Welche Information muss man der Methode mitgeben, damit sie arbeiten kann? | |||
** <u>Rückgabetyp</u> der Methoden: Gibt die Methode eine Information zurück? Welchen Datentyp hat die Rückgabe? | |||
==Beziehungen zwischen Klassen== | |||
Folgende Fragestellungen helfen beim Erstellen von Beziehungen: | |||
* <u>Kennt-Beziehung / Assoziation</u>: <u>Kennt</u> ein Objekt der Klasse A ein (oder mehrere) Objekt(e) der Klasse B? | |||
** <u>Multiplizität</u>: <u>Wieviele</u> Objekte der Klasse B? | |||
* <u>Vererbung</u>: Welches Objekt <u>ist ein</u> Objekt einer anderen Klasse? Welche Klasse <u>erbt</u> Attribute und Methoden einer anderen Klasse? | |||
=Erstellen von Implementationsdiagrammen: Top-Down-Modellierung= | |||
Für das Erstellen von Implementationsdiagrammen gibt es keine festen Regeln, aber eine geeignete Vorgehensweise, die '''Top-Down-Modellierung''': | |||
* Man ermittelt die Klassen, die sich aus dem Sachzusammenhang ergeben. | |||
* Man fängt bei der "obersten" Klasse an, die über allem steht und arbeitet sich immer weiter nach unten durch. Dabei stellt man fest, welche Beziehung zwischen den Klassen besteht. | |||
* Man zeichnet ein Implementationsdiagramm, in dem die Beziehungen zwischen den Klassen festgehalten werden. | |||
* Man zeichnet Klassendiagramme für die einzelnen Klassen, in denen Attribute und Methoden festgehalten werden. | |||
==Beispiel für die EF== | |||
===Szenario:=== | |||
Peter hat einen Motorroller. In der Nähe gibt es eine Tankstelle, bei der Peter tanken kann. | |||
Einige von Peters Freunden haben auch Motorroller. | |||
Es soll jetzt eine Anwendung entwickelt werden, in der das Fahren und Betanken der Motorroller simuliert werden kann. Auch das Bezahlen vom eigenen Guthaben soll simuliert werden. | |||
===ausführliches Klassendiagramm:=== | |||
[[File:Klassendiagramm-Roller-Tankstelle.png|Vollständiges Klassendiagramm|681px]] | |||
===Java-Quelltext:=== | |||
In den Quelltexten sind '''fett''' gedruckt die Teile, die die Beziehungen zwischen den Klassen herstellen. | |||
'''Klasse <code>Person</code>''' | |||
<code> | |||
public class Person | |||
{ | |||
'''private Roller meinRoller;''' | |||
'''private Tankstelle dieTankstelle;''' | |||
private String name; | |||
private double geld; | |||
public Person(String pName) | |||
{ | |||
name = pName; | |||
'''meinRoller = new Roller();''' | |||
} | |||
'''public void setTankstelle(Tankstelle pTankstelle)''' | |||
'''{''' | |||
'''dieTankstelle = pTankstelle;''' | |||
'''}''' | |||
public void geldErhoehen(double pBetrag) | |||
{ | |||
geld += pBetrag; | |||
} | |||
public boolean geldVermindern(double pBetrag) | |||
{ | |||
if(geld < pBetrag){ | |||
return false; | |||
} | |||
geld -= pBetrag; | |||
return true; | |||
} | |||
public boolean tanken(double pLiter) | |||
{ | |||
'''double kosten = dieTankstelle.tanken(pLiter)'''; | |||
if(kosten > geld) | |||
{ | |||
return false; | |||
} | |||
'''boolean erfolg = meinRoller.tanken(pLiter)'''; | |||
if(erfolg == false) | |||
{ | |||
return false; | |||
} | |||
geld -= kosten; | |||
return true; | |||
} | |||
public boolean fahren(double pKm) | |||
{ | |||
'''boolean erfolg = meinRoller.fahren(pKm);''' | |||
return erfolg; | |||
} | |||
} | |||
</code> | |||
'''Erklärung:''' | |||
* Die hat-Beziehung zwischen <code>Person</code> und <code>Roller</code> wird hergestellt, indem im Konstruktor von <code>Person</code> ein <code>Roller</code> erzeugt wird. | |||
* Dieser <code>Roller</code> wird im Attribut <code>meinRoller</code> gespeichert. | |||
* Die <code>Person</code> kann jetzt Aufgaben an <code>meinRoller</code> '''delegieren''', indem sie geeignete Methoden von <code>meinRoller</code> aufruft. | |||
* Die kennt-Beziehung zwischen <code>Roller</code> und <code>Tankstelle</code> wird durch die Methode <code>setTankstelle</code> hergestellt. | |||
* Die <code>Person</code> kann jetzt das <code>tanken</code> an die <code>Tankstelle</code> '''delegieren'''. | |||
'''Klasse Simulation''' | |||
Diese Klasse erscheint nicht im Klassendiagramm, ist aber sinnvoll, um die Simulation überhaut starten zu können. Hier wird die Beziehung zwischen <code>Person</code> und <code>Roller</code> hergestellt. | |||
<code> | |||
public class Simulation | |||
{ | |||
private Person frank; | |||
private Tankstelle aral; | |||
public Simulation(){ | |||
frank = new Person("Frank"); | |||
aral = new Tankstelle("Aral"); | |||
aral.setPreis(1.43); | |||
frank.setTankstelle(aral); | |||
} | |||
} | |||
</code> | |||
==Beispiel für die Q1 (Listen)== | |||
'''Szenario:''' | |||
Ein Medienplayer kann die Titel, die man hören möchte, in Wiedergabelisten verwalten. Folgende typische Operationen sollen im Modell enthalten sein: | |||
# Für einen Titel werden der Name, der Interpret und die Länge in Sekunden gespeichert. (Um die Speicherung der Audio-Daten kümmert sich diese Modellierung nicht.) | |||
# Ein Titel kann an einer beliebigen Position der Wiedergabeliste (d. h. am Anfang, am Ende oder an einer Stelle innerhalb der Liste) eingefügt werden. Ebenso kann ein beliebiger Titel aus der Liste gelöscht werden. | |||
# Das Abspielen der Wiedergabeliste beginnt beim ersten Titel. Dann werden alle Titel nacheinander abgespielt. Man kann das Abspielen stoppen. Und man kann wieder an den Anfang der Wiedergabeliste gehen. | |||
# In einem Medienplayer werden beliebig viele Wiedergabelisten verwaltet. Jede Wiedergabeliste hat einen Namen. Der Medienplayer kann immer nur eine aktive Wiedergabeliste haben. Die aktive Liste kann abgespielt werden. | |||
# Im Medienplayer kann man eine Wiedergabeliste auswählen, indem man ihren Namen angibt. Man kann auch neue Wiedergabelisten anlegen, indem man einen Namen angibt. Und man kann die gerade aktive Wiedergabeliste löschen. | |||
# Beim Abspielen einer Wiedergabeliste fragt der Medienplayer immer den nächsten Titel von der aktiven Wiedergabeliste an. | |||
'''Aufgabe''': | |||
Entwerfen Sie ein Implementationsdiagramm. Begründen Sie Ihre Entscheidungen. Begründen Sie auch, ob Sie sich für <code>Stack</code>, <code>Queue</code> oder <code>List</code> entscheiden. | |||
==Lösung== | |||
===Analyse=== | |||
Bei der Analyse schreibt man formelhaft Begründungen für die Beziehungen der Klassen: | |||
* Aus dem Szenario ergeben sich die Klassen <code>Medienplayer</code>, <code>Wiedergabeliste</code> und <code>Titel</code>. | |||
* <code>Medienplayer</code> ist die "oberste" Klasse und damit der Ausgangspunkt der Modellierung. | |||
* <code>Medienplayer</code> '''hat''' eine Liste mit '''Inhaltsobjekten''' vom Typ <code>Wiedergabeliste</code>. <code>List</code> eignet sich besser als <code>Queue</code> oder <code>Stack</code>, weil damit das Auswählen der Wiedergabeliste nach dem Titel einfacher realisiert werden kann. | |||
* <code>Medienplayer</code> '''hat''' ein Attribut <code>aktiveWiedergabeliste</code> vom Typ <code>Wiedergabeliste</code>, in dem die jeweils aktive Wiedergabeliste gespeichert wird. | |||
* <code>WiedergabeListe</code> kann nicht von <code>List</code> '''erben''', weil sie sonst die Methode <code>concat(List pList)</code> zur Verfügung hätte, die im Szenario nicht vorgesehen ist. | |||
* Stattdessen: <code>WiedergabeListe</code> '''hat''' eine <code>List</code> mit '''Inhaltsobjekten''' vom Typ <code>Titel</code>. <code>Queue</code> oder <code>Stack</code> eignen sich nicht, weil man an beliebigen Stellen einfügen können muss. | |||
===Implementationsdiagramm: Beziehung der Klassen=== | |||
Zuerst werden nur die Beziehungen zwischen den Klassen in einem Diagramm dargestellt. | |||
Attribute und Methoden werden noch nicht dargestellt. Das erleichtert WESENTLICH die Modellierung und das Zeichnen! | |||
[[Datei:Medienplayer-beziehungen.png]] | |||
===Implementationsdiagramm: Die einzelnen Klassen=== | |||
Jetzt werden die einzelnen Klassen mit Attributen und Methoden dargestellt. | |||
[[Datei:Medienplayer-klassen.png]] | |||
=Implementationsdiagramme erläutern= | |||
Eine mögliche Aufgabenstellung kann sein: | |||
''Beschreiben Sie die dargestellten Klassen und deren Beziehungen zueinander.'' | |||
Hier kommt es darauf an, dass man '''Fachbegriffe''' verwendet!! | |||
==Beispiel== | |||
[[Datei:Implementationsdiagramm-medienplayer.png]] | |||
'''Aufgabe:''' | |||
''Beschreiben Sie die dargestellten Klassen und deren Beziehungen zueinander.'' | |||
'''Mögliche Lösung:''' | |||
''Fachbegriffe sind jeweils <u>unterstrichen</u>, wenn sie das erste Mal vorkommen.'' | |||
'''Beschreibung der Klassen: ''' | |||
* Die <u>Klasse</u> Titel hat drei <u>private Attribute</u>. Im <u>Konstruktor</u> muss an Werte für die drei Attribute angeben. Es gibt für jedes Attribut eine <u>öffentliche get-Methode</u>. | |||
* Die Klasse Wiedergabeliste hat ein privates Attribut name; dafür muss man im Konstruktor einen Wert angeben. Außerdem gibt es eine öffentliche get-Methode für name. | |||
* Die Klasse Wiedergabeliste hat weitere öffentliche Methoden, z.T. mit <u>Parametern</u> vom <u>Typ</u> Song. Die Methoden geben nichts zurück. | |||
* Die Klasse Medienplayer hat - abgesehen von wiedergabeListen (s.u.) - keine Attribute. Der Konstruktor hat keine Parameter. Es gibt drei öffentliche Methoden mit Parameter vom Typ String; eine Methode gibt ein boolean zurück, die anderen beiden geben nichts zurück. | |||
'''Beschreibung der Beziehungen:''' | |||
* Die Klasse Wiedergabeliste hat ein <u>privates Attribut songListe vom Typ List. Die Liste enthält Objekte vom Typ Song</u>. | |||
* Die Klasse Medienplayer hat ein privates Attribut wiedergabeListen vom Typ List. Die Liste enthält Objekte vom Wiedergabeliste. |
Aktuelle Version vom 11. Januar 2024, 19:43 Uhr
- Klassendiagramme sind wesentlicher Bestandteil der UML (=Unified Modeling Language).
- Implementationsdiagramme gibt es nur in Nordrhein-Westfalen!
Fachbegriffe
- Klasse, Objekt
- hat-Beziehung, kennt, erbt von, "hat ein Attribut ... vom Typ List, das nur Objekte vom Typ... enthalten kann"
- Attribut, Attribut-Typ
- Methode, Parameter, Parameter-Typ, Rückgabe-Typ, öffentliche Methode, private Methode
- get-Methode (=gibt nur ein Attribut zurück), set-Methode (=trägt nur einen neuen Wert in ein Attribut ein)
- Geheimnisprinzip
Wofür braucht man Klassen- und Implementationsdiagramme?
Klassendiagramme braucht man, um Softwaresysteme zu modellieren. Dabei wird im Klassendiagramm folgendes festgelegt:
- Name, Attribute (mit Typ) und Methoden (mit Parameter und Rückgabetyp) jeder einzelnen Klasse.
- Die Beziehungen zwischen den Klassen.
Nicht festgelegt wird im Klassendiagramm die konkrete Programmierung.
Sehr vereinfacht sieht der Entwicklungsprozess so aus:
Aus der Anforderungsermittlung (=einem Text, der mit dem Auftraggeber abgesprochen ist) zeichnet der Software-Architekt Klassendiagramme, die die gesamte in der Anforderungsermittlung beschriebene Funktionalität abbilden. In großen Systemen kann es mehrere hundert Klassen geben.
Anschließend können die Programmierer die im Klassendiagramm beschriebenen Klassen implementieren (z.B. in Java).
Anforderungen an Implementationsdiagramme
Die folgenden Anforderungen sind erst dann interessant, wenn man mehrere Klassen hat, die in Beziehung zueinander stehen!
Was hier im folgende steht, ist nicht gedeckt durch Literatur etc. Es hat sich aber für den Unterricht, in der (einfachen) Praxis und auch im Zentralabitur als brauchbar erwiesen.
Implementationsdiagramme sollen eine Software-Architektur für eine Software-Anwendung definieren.
Deswegen gibt es zwei Grundanforderungen, die klar sind:
- Die Anforderungen müssen mit der Software-Architektur möglichst einfach realisierbar sein.
- Die Software-Architektur soll sich möglichst einfach implementieren lassen, d.h. in Quellcode übersetzen lassen.
Daraus lassen sich folgende Anforderungen ableiten:
Intuitiv verständlich
Objektorientierung lebt davon, dass man mit ihrer Hilfe Szenarien aus der realen Welt möglichst "realitätsnah" modellieren und implementieren kann. Das sollte man nutzen, und deswegen sollten Implementationsdiagramme intuitiv verständlich sein.
Geheimnisprinzip:
Jede Klasse sollte die Daten, die sie verwaltet, privat halten und nur einen kontrollierten Zugriff darauf bieten.
Beispiel: Die Klasse Fahrkartenautomat
sollte auf keinen Fall das Attribut eingeworfenesGeld
öffentlich machen! Wer weiß, was ein anderer Programmierer dann damit tut??! Stattdessen sollte es eine Methode geldEinwerfen
geben, bei der der Fahrkartenautomat den Zugriff auf eingeworfenesGeld
steuern kann.
Möglichst Beziehungen nur in einer Richtung:
Das erleichtert später die Implementierung!
möglichst Top-Down:
Streng Hierachische Architekturen sind in der Regel leicht beherrschbar. Die Beziehungen gehen dann in der Regel von oben nach unten. Wenn ganz an der Spitze eine Klasse steht, die "alles kontrolliert", kann diese Klasse Aufgaben an untergeordnete Klassen delegieren.
Vorgaben für das Zentralabitur
Hier die offiziellen Erläuterungen für Klassen- und Implementationsdiagramme:
Klassen- und Implementationsdiagramme (PDF)
Attribute und Methoden im Klassendiagramm
Rechts ein einfaches Klassendiagramm für die Klasse Buch: Die Klasse Buch ist ein bloßer Informationsbehälter, d.h. die Klasse verfügt nur über get- und set-Methoden und nicht über eine eigene Logik.
Aufbau eines Klassendiagramms
Klassendiagramme haben immer drei Zeilen:
- Zeile: Der Name der Klasse
- Zeile: die Attribute der Klasse
- Zeile: die Methoden der Klasse
- Dabei wird als erstes der Konstruktor aufgeführt.
Syntax innerhalb des Klassendiagramms
Klassendiagramme haben eine eigene Syntax, die (leider!) von der Java-Syntax abweicht:
- + bedeutet
public
- - bedeutet
private
- Attribute:
- VOR dem Doppelpunkt: "+" bzw. "-" und der Attribut-Name
- NACH dem Doppelpunkt: Attribut-Typ
- Methoden:
- erst "+" bzw. "-" (für
public
bzw.private
) - Methoden-Name
- Parameter (in Klammern!): VOR dem Doppelpunkt der Parameter-Name, NACH dem Doppelpunkt der Parameter-Typ.
- NACH dem Doppelpunkt: Rückgabe-Typ der Methode
- erst "+" bzw. "-" (für
Java-Implementierung
Wie die einzelnen Klassen implementiert werden, das entscheidet der zuständige Programmierer; er muss sich aber genau an die Vorgaben des Klassendiagramms halten.
Das oben gegebene einfache Klassendiagramm kann z.B. wie folgt in Java implementiert werden.
public class Buch{
//Attribute
private String titel;
private int regalNr;
//Konstruktor
public Buch(String pTitel){
titel = pTitel;
}
// get- und set-Methoden
public int getRegalNr() {
return regalNr;
}
public void setRegalNr(int pRegalNr) {
regalNr = pRegalNr;
}
public String getTitel() {
return titel;
}
}
Beziehungen zwischen Klassen
Es gibt zwei Beziehungstypen:
- Kennt-Beziehung (Assoziation): Ein Objekt der Klasse A kennt ein/mehrere Objekte der Klasse B.
Beispiel: Fahrer kennt mehrere Tankstellen. - Vererbung: Klasse A erbt von Klasse B. Man sagt auch oft: A ist ein B
Beispiel: Roller erbt von Fahrzeug, bzw. Roller ist ein Fahrzeug.
Anmerkung:
Im UML-Standard gibt es noch einen dritten Beziehungstyp:
Hat-Beziehung: Ein Objekt der Klasse A hat (=besitzt!) ein/mehrere Objekte der Klasse B.
Beispiel: Fahrer hat einen Roller.
Im Zentralabitur wird aber zwischen kennt-Beziehung und hat-Beziehung nicht unterschieden.
Multiplizitäten der Kennt-Beziehung
Multiplizitäten werden entweder genau oder mit einer Unter- und einer Obergrenze notiert.
Beispiele:
- 1: genau ein
- 0..1: 0 oder ein
- 2..4: mindestens 2 und höchstens 4
- 1..*: mindestens 1 (und höchstens beliebig viele)
Beispiel
Im Klassendiagramm rechts sind die Beziehungen zwischen Roller, Fahrer und Tankstelle dargestellt. (Attribute und Methoden der einzelnen Klassen sind hier nicht aufgeführt.
Erläuterung:
- Jeder Fahrer kennt genau einen (nämlich seinen) Roller.
- Jeder Fahrer kennt mindestens eine, aber beliebig viele Tankstellen.
Erstellen von Klassendiagrammen
Klassendiagramme sind vor allem Planungswerkzeuge für die Entwicklung umfangreicher Software-Systeme.
Mithilfe von Klassendiagrammen kann man festlegen, was programmiert werden muss.
Attribute, Konstruktor, Methoden
Folgende Fragestellungen helfen beim Erstellen von Klassendiagrammen:
- Attribute: Welche Informationen müssen Objekte der Klasse speichern, damit sie im Szenario funktionieren können?
- Parameter des Konstruktors: Welche Information muss man angeben, wenn man ein Objekt der Klasse erzeugt?
- Methoden: Was kann man mit Objekten der Klasse tun?
- Parameter der Methoden: Welche Information muss man der Methode mitgeben, damit sie arbeiten kann?
- Rückgabetyp der Methoden: Gibt die Methode eine Information zurück? Welchen Datentyp hat die Rückgabe?
Beziehungen zwischen Klassen
Folgende Fragestellungen helfen beim Erstellen von Beziehungen:
- Kennt-Beziehung / Assoziation: Kennt ein Objekt der Klasse A ein (oder mehrere) Objekt(e) der Klasse B?
- Multiplizität: Wieviele Objekte der Klasse B?
- Vererbung: Welches Objekt ist ein Objekt einer anderen Klasse? Welche Klasse erbt Attribute und Methoden einer anderen Klasse?
Erstellen von Implementationsdiagrammen: Top-Down-Modellierung
Für das Erstellen von Implementationsdiagrammen gibt es keine festen Regeln, aber eine geeignete Vorgehensweise, die Top-Down-Modellierung:
- Man ermittelt die Klassen, die sich aus dem Sachzusammenhang ergeben.
- Man fängt bei der "obersten" Klasse an, die über allem steht und arbeitet sich immer weiter nach unten durch. Dabei stellt man fest, welche Beziehung zwischen den Klassen besteht.
- Man zeichnet ein Implementationsdiagramm, in dem die Beziehungen zwischen den Klassen festgehalten werden.
- Man zeichnet Klassendiagramme für die einzelnen Klassen, in denen Attribute und Methoden festgehalten werden.
Beispiel für die EF
Szenario:
Peter hat einen Motorroller. In der Nähe gibt es eine Tankstelle, bei der Peter tanken kann. Einige von Peters Freunden haben auch Motorroller.
Es soll jetzt eine Anwendung entwickelt werden, in der das Fahren und Betanken der Motorroller simuliert werden kann. Auch das Bezahlen vom eigenen Guthaben soll simuliert werden.
ausführliches Klassendiagramm:
Java-Quelltext:
In den Quelltexten sind fett gedruckt die Teile, die die Beziehungen zwischen den Klassen herstellen.
Klasse Person
public class Person
{
private Roller meinRoller;
private Tankstelle dieTankstelle;
private String name;
private double geld;
public Person(String pName)
{
name = pName;
meinRoller = new Roller();
}
public void setTankstelle(Tankstelle pTankstelle)
{
dieTankstelle = pTankstelle;
}
public void geldErhoehen(double pBetrag)
{
geld += pBetrag;
}
public boolean geldVermindern(double pBetrag)
{
if(geld < pBetrag){
return false;
}
geld -= pBetrag;
return true;
}
public boolean tanken(double pLiter)
{
double kosten = dieTankstelle.tanken(pLiter);
if(kosten > geld)
{
return false;
}
boolean erfolg = meinRoller.tanken(pLiter);
if(erfolg == false)
{
return false;
}
geld -= kosten;
return true;
}
public boolean fahren(double pKm)
{
boolean erfolg = meinRoller.fahren(pKm);
return erfolg;
}
}
Erklärung:
- Die hat-Beziehung zwischen
Person
undRoller
wird hergestellt, indem im Konstruktor vonPerson
einRoller
erzeugt wird. - Dieser
Roller
wird im AttributmeinRoller
gespeichert. - Die
Person
kann jetzt Aufgaben anmeinRoller
delegieren, indem sie geeignete Methoden vonmeinRoller
aufruft. - Die kennt-Beziehung zwischen
Roller
undTankstelle
wird durch die MethodesetTankstelle
hergestellt. - Die
Person
kann jetzt dastanken
an dieTankstelle
delegieren.
Klasse Simulation
Diese Klasse erscheint nicht im Klassendiagramm, ist aber sinnvoll, um die Simulation überhaut starten zu können. Hier wird die Beziehung zwischen Person
und Roller
hergestellt.
public class Simulation
{
private Person frank;
private Tankstelle aral;
public Simulation(){
frank = new Person("Frank");
aral = new Tankstelle("Aral");
aral.setPreis(1.43);
frank.setTankstelle(aral);
}
}
Beispiel für die Q1 (Listen)
Szenario:
Ein Medienplayer kann die Titel, die man hören möchte, in Wiedergabelisten verwalten. Folgende typische Operationen sollen im Modell enthalten sein:
- Für einen Titel werden der Name, der Interpret und die Länge in Sekunden gespeichert. (Um die Speicherung der Audio-Daten kümmert sich diese Modellierung nicht.)
- Ein Titel kann an einer beliebigen Position der Wiedergabeliste (d. h. am Anfang, am Ende oder an einer Stelle innerhalb der Liste) eingefügt werden. Ebenso kann ein beliebiger Titel aus der Liste gelöscht werden.
- Das Abspielen der Wiedergabeliste beginnt beim ersten Titel. Dann werden alle Titel nacheinander abgespielt. Man kann das Abspielen stoppen. Und man kann wieder an den Anfang der Wiedergabeliste gehen.
- In einem Medienplayer werden beliebig viele Wiedergabelisten verwaltet. Jede Wiedergabeliste hat einen Namen. Der Medienplayer kann immer nur eine aktive Wiedergabeliste haben. Die aktive Liste kann abgespielt werden.
- Im Medienplayer kann man eine Wiedergabeliste auswählen, indem man ihren Namen angibt. Man kann auch neue Wiedergabelisten anlegen, indem man einen Namen angibt. Und man kann die gerade aktive Wiedergabeliste löschen.
- Beim Abspielen einer Wiedergabeliste fragt der Medienplayer immer den nächsten Titel von der aktiven Wiedergabeliste an.
Aufgabe:
Entwerfen Sie ein Implementationsdiagramm. Begründen Sie Ihre Entscheidungen. Begründen Sie auch, ob Sie sich für Stack
, Queue
oder List
entscheiden.
Lösung
Analyse
Bei der Analyse schreibt man formelhaft Begründungen für die Beziehungen der Klassen:
- Aus dem Szenario ergeben sich die Klassen
Medienplayer
,Wiedergabeliste
undTitel
. Medienplayer
ist die "oberste" Klasse und damit der Ausgangspunkt der Modellierung.Medienplayer
hat eine Liste mit Inhaltsobjekten vom TypWiedergabeliste
.List
eignet sich besser alsQueue
oderStack
, weil damit das Auswählen der Wiedergabeliste nach dem Titel einfacher realisiert werden kann.Medienplayer
hat ein AttributaktiveWiedergabeliste
vom TypWiedergabeliste
, in dem die jeweils aktive Wiedergabeliste gespeichert wird.WiedergabeListe
kann nicht vonList
erben, weil sie sonst die Methodeconcat(List pList)
zur Verfügung hätte, die im Szenario nicht vorgesehen ist.- Stattdessen:
WiedergabeListe
hat eineList
mit Inhaltsobjekten vom TypTitel
.Queue
oderStack
eignen sich nicht, weil man an beliebigen Stellen einfügen können muss.
Implementationsdiagramm: Beziehung der Klassen
Zuerst werden nur die Beziehungen zwischen den Klassen in einem Diagramm dargestellt.
Attribute und Methoden werden noch nicht dargestellt. Das erleichtert WESENTLICH die Modellierung und das Zeichnen!
Implementationsdiagramm: Die einzelnen Klassen
Jetzt werden die einzelnen Klassen mit Attributen und Methoden dargestellt.
Implementationsdiagramme erläutern
Eine mögliche Aufgabenstellung kann sein:
Beschreiben Sie die dargestellten Klassen und deren Beziehungen zueinander.
Hier kommt es darauf an, dass man Fachbegriffe verwendet!!
Beispiel
Aufgabe: Beschreiben Sie die dargestellten Klassen und deren Beziehungen zueinander.
Mögliche Lösung:
Fachbegriffe sind jeweils unterstrichen, wenn sie das erste Mal vorkommen.
Beschreibung der Klassen:
- Die Klasse Titel hat drei private Attribute. Im Konstruktor muss an Werte für die drei Attribute angeben. Es gibt für jedes Attribut eine öffentliche get-Methode.
- Die Klasse Wiedergabeliste hat ein privates Attribut name; dafür muss man im Konstruktor einen Wert angeben. Außerdem gibt es eine öffentliche get-Methode für name.
- Die Klasse Wiedergabeliste hat weitere öffentliche Methoden, z.T. mit Parametern vom Typ Song. Die Methoden geben nichts zurück.
- Die Klasse Medienplayer hat - abgesehen von wiedergabeListen (s.u.) - keine Attribute. Der Konstruktor hat keine Parameter. Es gibt drei öffentliche Methoden mit Parameter vom Typ String; eine Methode gibt ein boolean zurück, die anderen beiden geben nichts zurück.
Beschreibung der Beziehungen:
- Die Klasse Wiedergabeliste hat ein privates Attribut songListe vom Typ List. Die Liste enthält Objekte vom Typ Song.
- Die Klasse Medienplayer hat ein privates Attribut wiedergabeListen vom Typ List. Die Liste enthält Objekte vom Wiedergabeliste.