UML Klassendiagramm: Unterschied zwischen den Versionen
Drlue (Diskussion | Beiträge) |
Drlue (Diskussion | Beiträge) |
||
| (15 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 7: | Zeile 7: | ||
Ein '''Klassendiagramm''' wird verwendet, um die Softwarearchitektur einfacher und übersichtlicher darzustellen und diese dann anschließend leichter umsetzen zu können. | Ein '''Klassendiagramm''' wird verwendet, um die Softwarearchitektur einfacher und übersichtlicher darzustellen und diese dann anschließend leichter umsetzen zu können. | ||
<br> | |||
Weiters kann auch aus bestehendem Quellcode ein '''Klassendiagramm''' erstellt werden. Dies kann zu Dokumentationszwecken oder auch zur besseren Veranschaulichung gemacht werden. | |||
== Bausteine eines Klassendiagramms == | == Bausteine eines Klassendiagramms == | ||
| Zeile 136: | Zeile 138: | ||
Klasse cls = new Klasse(); | Klasse cls = new Klasse(); | ||
//Aufruf nur möglich wenn in der selben Klasse | //Aufruf nur möglich wenn in der selben Klasse | ||
cls.count(10,20); | cls.count(10,20);abstrakten Klassen | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Abstrakte Klassen und Methoden === | |||
Bei '''abstrakten Klassen''' (siehe {{AL|Abstrakte_Klasse|Abstrakte Klasse}}) wird der Name ''kursiv'' geschrieben. Weiters werden auch die '''abstrakte Methoden''' ''kursiv'' geschrieben. | |||
== Schnittstellen == | == Schnittstellen == | ||
| Zeile 150: | Zeile 155: | ||
'''Moveable.java''' | '''Moveable.java''' | ||
<syntaxhighlight lang="java" line> | <syntaxhighlight lang="java" line> | ||
interface Moveable { | public interface Moveable { | ||
int left(int x); | int left(int x); | ||
| Zeile 164: | Zeile 169: | ||
'''Rectangle.java''' | '''Rectangle.java''' | ||
<syntaxhighlight lang="java" line> | <syntaxhighlight lang="java" line> | ||
public class Rectangle implements Moveable{ | public class Rectangle implements Moveable { | ||
int positionx; | public int positionx; | ||
int positiony; | public int positiony; | ||
int positionz; | public int positionz; | ||
@Override | @Override | ||
| Zeile 204: | Zeile 209: | ||
== Generalisierung == | == Generalisierung == | ||
Durch eine '''Generalisierung''' '''erben''' '''speziellere Klassen''' von '''generelleren Klassen'''. Dadurch werden bestimmte Merkmale von der '''generellen Klasse''' an die '''spezialisierte Klasse''' '''vererbt'''. Die Pfeilspitze der '''Generalisierung''' zeigt auf die '''Oberklasse''' ('''Klasse''' von | Durch eine '''Generalisierung''' '''erben''' '''speziellere Klassen''' von '''generelleren Klassen'''. Dadurch werden bestimmte Merkmale von der '''generellen Klasse''' an die '''spezialisierte Klasse''' '''vererbt'''. Die Pfeilspitze der '''Generalisierung''' zeigt auf die '''Oberklasse''' ('''Klasse''' von welcher '''geerbt''' wird). | ||
[[Datei:Generalization (UML class diagram).png|mini|none|100px|Generalisierung]] | [[Datei:Generalization (UML class diagram).png|mini|none|100px|Generalisierung]] | ||
Im Folgenden wird ein Beispiel zum besseren Verständnis von '''Generalisierungen''' gezeigt: | Im Folgenden wird ein Beispiel zum besseren Verständnis von '''Generalisierungen''' gezeigt: | ||
[[Datei:2021-01-29 Generalisierung.jpg|mini|none|Generalisierung]] | [[Datei:2021-01-29 Generalisierung.jpg|mini|none|Generalisierung - '''Achtung Klassenname ''Animal'' und die Methode ''move()'' sollten kursiv sein''']] | ||
In dem oben dargestellten Bild sieht man eine '''Generalisierung''' zwischen einer '''abstrakten''' und einer '''normalen Klassen'''. Die Umsetzung in Java würde wie folgt aussehen: | In dem oben dargestellten Bild sieht man eine '''Generalisierung''' zwischen einer '''abstrakten''' und einer '''normalen Klassen'''. Die Umsetzung in Java würde wie folgt aussehen: | ||
| Zeile 247: | Zeile 252: | ||
== Assoziation == | == Assoziation == | ||
Eine '''Assoziation''' bezeichnet eine '''Beziehung''' zwischen zwei oder mehreren {{Link|Klasse|Klassen}}, wobei die häufigste Verbindung zwischen genau zwei Klassen aufritt. Es gibt folgende zwei Arten von '''Assoziationen''': | |||
=== N-äre Assoziation === | |||
In folgenden Bild sieht man eine '''Binäre Assoziation'''. ('''Binär''', weil zwei {{Link|Klasse|Klassen}} miteinander verbunden wurden) | |||
[[Datei:1920px-UmlCd Assoziation-1.png|mini|none|Binäre Assoziation]] | |||
In folgenden Bild sieht man eine Binäre Assoziation. (Binär, weil zwei Klassen miteinander verbunden wurden) | === Reflexive Assoziation === | ||
[[Datei:1920px-UmlCd Assoziation-1.png|mini| | Im hier dargestellten Bild sieht man eine '''reflexive Assoziation''', welche auf sich selbst verweist. | ||
[[Datei:UmlCd Assoziation-2.png|mini|none|Reflexive Assoziation]] | |||
=== Eigenschaften von Assoziationen === | |||
Da '''Assoziationen''' durch Linien dargestellt werden, müssen diese durch ein '''Assoziationsende''' gekennzeichnet werden. Diese '''Assoziationsenden''' können folgende Merkmale aufweisen: | |||
* Sie können eine '''Multiplizität''' besitzen. Diese enthält Informationen über das Beziehungsverhältnis zweier {{Link|Klasse|Klassen}}. Diese Zahlen befinden sich '''nur''' im '''positiven''' und '''ganzzahligen''' Bereich, wobei der Beginn bei der '''Zahl 0''' liegt. | |||
Im hier dargestellten Bild sieht man eine reflexive Assoziation, welche auf sich selbst verweist. | |||
[[Datei:UmlCd Assoziation-2.png|mini| | |||
Da Assoziationen durch Linien dargestellt werden, müssen diese durch ein Assoziationsende gekennzeichnet werden. Diese Assoziationsenden können folgende Merkmale aufweisen: | |||
* Sie können eine Multiplizität besitzen. Diese | |||
** Multiplizitäten werden im folgenden Format angegeben: | ** Multiplizitäten werden im folgenden Format angegeben: | ||
untereSchranke..obereSchranke | untereSchranke..obereSchranke | ||
** Bei * oder auch 0..* wird die untereSchranke als 0 und die obereSchranke als unendlich angenommen. | ** Bei '''*''' oder auch '''0..*''' wird die untereSchranke als 0 und die obereSchranke als unendlich angenommen. | ||
** Beide Schranken dürfen nicht 0 oder unbeschränkt sein. Falls beide Grenzen trotzdem gleich groß sind, wird nur die obereSchranke angegeben. | ** Beide Schranken dürfen nicht 0 oder unbeschränkt sein. Falls beide Grenzen trotzdem gleich groß sind, wird nur die obereSchranke angegeben. | ||
** Bei einer Multiplizität von 0..1 wird das Element als ''optional'' bezeichnet. | ** Bei einer Multiplizität von 0..1 wird das Element als ''optional'' bezeichnet. | ||
** Wenn die obereSchranke über dem Wert 1 liegt, wird das Element als mehrwertiges Element bezeichnet, da mehrere Wert annehmbar sind. | ** Wenn die obereSchranke über dem Wert 1 liegt, wird das Element als mehrwertiges Element bezeichnet, da mehrere Wert annehmbar sind. | ||
* Sie können Namen besitzen. | * Sie können '''Namen''' besitzen. | ||
* Sie können eine Sichtbarkeit aufweisen. | * Sie können eine '''Sichtbarkeit''' aufweisen. | ||
* Es kann spezifiziert werden, ob das Assoziationsende | * Es kann spezifiziert werden, ob das Assoziationsende '''ordered''' und/oder '''unique''' ist. | ||
Zum '''Assoziationsende''' kommen oft '''Multiplizitäten''' hinzu, welche die '''Beziehung''' zwischen den zwei Instanzen regelt. Im folgenden wird auf zwei Arten der Assoziationen genauer eingegangen. | |||
'''Tip um die Multiplizität korrekt zu bestimmen''' | |||
<br>'''Beispiel:''' Raum und Gebäude<br> | |||
Es kann immer folgende Frage gestellt werden:<br> | |||
'''Ein Raum ist in wievielen Gebäuden?''' In einem also kommt eine 1 zum Gebäude.<br>'''Ein Gebäude hat wieviele Räume?''' Einen oder mehrere also kommt ein 1..* zum Raum.<br> | |||
== | === Komposition und Aggregation === | ||
Um Beziehungen mit ''Ganzen'' und ''Teilen'' darzustellen werden die '''Aggregation''' und die '''Komposition''' verwendet. | |||
==== Komposition ==== | |||
[[Datei:Komposition Aggregation.png|mini|mini|Komposition und Aggregation]] | |||
Die graphische Darstellung einer '''Komposition''' ist eine Linie mit einer ausgefüllten Raute, welche mit der Kardinalität 1 beschriftet wird und mit dem Ganzen Teil der Beziehungspartner verbunden ist. Bei einer Komposition können die ''Teile'' nicht ohne das ''Ganze'' existieren. Das bedeutet, dass das '''Teil''' Element existenziell abhängig vom '''Ganz''' Element ist. | |||
==== Aggregation ==== | |||
Die graphische Darstellung einer '''Aggregation''' ist eine Linie mit einer nicht ausgefüllten Raute, welche die Kardinalität 0..* besitzt und mit dem '''Ganzen''' Teil verbunden ist. Die Elemente in einer Aggregation besitzen keine Exisitenzabhängigkeit, da die '''Teil''' Elemente auch ohne die ''Ganz'' Elemente bestehen können.<br> | |||
Die Assoziationsarten werden prinzipiell mittels der Kardinalität unterschieden. Zudem sind die '''Teil''' Elemente Bestandteil genau eines ''Ganz'' Elementes, da sie NIE zu mehrere '''Ganz''' Elementen gehören. | |||
Diese Umsetzung erfolgte mit der Programmiersprache | == Beispiel mit Umsetzung == | ||
Diese Umsetzung erfolgte mit der Programmiersprache Java. | |||
[[Datei:Screenshot 2021-01-22 143552.jpg|mini|600px|none|Fahrzeuge in einem UML Klassendiagramm]] | [[Datei:Screenshot 2021-01-22 143552.jpg|mini|600px|none|Fahrzeuge in einem UML Klassendiagramm]] | ||
'''Vehicle.java''' | '''Vehicle.java''' | ||
Aktuelle Version vom 5. März 2021, 10:08 Uhr
Das Klassendiagramm bildet ein Kernstück der Unified Modeling Language (UML). Zudem beruht dieses Diagramm auf den Prinzipien der Objektorientierung, wobei der Diagrammtyp vielseitige Anwendung findet.
Beispielsweise wird dieses Modell in der Analysephase als Domänenmodell verwendet, um ein reales Abbild zu erstellen. In der Designphase wird mit diesem Modell eine Software modelliert, wobei in der Implementierungsphase aus dem Modell Code generiert wird.
Ein Domänenmodell ist ein konzeptionelles Modell der Domäne, das sowohl Verhalten als auch Daten enthält. Die Domäne oder english Domain ist der Kontext bzw. das Umfeld in dem sich das Modell befindet.
Anwendungsgebiete von Klassendiagramme
Ein Klassendiagramm wird verwendet, um die Softwarearchitektur einfacher und übersichtlicher darzustellen und diese dann anschließend leichter umsetzen zu können.
Weiters kann auch aus bestehendem Quellcode ein Klassendiagramm erstellt werden. Dies kann zu Dokumentationszwecken oder auch zur besseren Veranschaulichung gemacht werden.
Bausteine eines Klassendiagramms
Klassenmodelle unterteilen sich in folgende Komponenten:
- Klassen
- Schnittstellen
- Generalisierung
- Assoziation
- Komposition
- Aggregation
Klassen

Klassen werden in UML durch Rechtecke dargestellt, welche ebenfalls den Namen der Klasse innerhalb des Rechtecks enthalten. Zudem kann eine Klasse auch Operationen (Methoden) und/oder Attribute (Eigenschaften/Variablen) haben. Weiter können über dem Klassennamen bestimmte Schlüsselwörter wie z.B. <<interface>> stehen. Außerdem besitzen die Operationen und Attribute der Klassen bestimmte Sichtbarkeiten, welche im Folgenden erklärt werden, siehe auch Sichtbarkeit, wobei diese nicht exakt die selbe Bedeutung wie in der UML besitzen (protected und package).
Sichtbarkeit
public oder auch +
Bei der public oder auch öffentlichen Sichtbarkeit wird keine Beschränkung über die Methoden oder Attribute vergeben. Somit kann auf diese Komponenten aus jeder Stelle im Modell zugegriffen werden.
protected oder auch #
Bei der protected Sichtbarkeit kann auf die Operationen und Attribute in der Klasse selbst, weiters von Klassen die von dieser Klasse erben, zugegriffen werden.
private oder auch −
Bei der private Sichtbarkeit kann auf die Operationen und Attribute nur in der Klasse selbst zugegriffen werden.
package oder auch ~
Bei der package Sichtbarkeit sind die Methoden und Attribute innerhalb des gleichen Packages aufrufbar.
Beispiele
Hier wird im Folgenden die Verwendung von Klassen anhand von Beispielen gezeigt.
public

Die oben dargestellte Klasse verfügt über zwei public Attribute und eine public Methode, wobei der Fokus auf den Attributen liegt. Der Code sieht wie folgt aus:
public class Klasse {
public int a;
public int b;
public int count(){
return this.a + this.b;
}
}

Dieses Bild zeigt eine Klasse mit keinen Attributen aber mit einer public Methode. Der Code dieses Bildes wurde folgendermaßen umgesetzt:
public class Klasse {
public int count(int a, int b){
return a + b;
}
}
...
public static void main(String[] args){
Klasse cls = new Klasse();
cls.count(10,20);
}
protected

Dieses Bild zeigt zwei protected Attribute und eine protected Methode. Die Umsetzung des Codes sieht wie folgt aus:
public class Klasse{
protected int a;
protected int b;
protected int divide(){
return this.a / this.b;
}
}

Dieses Bild zeigt eine protected Methode ohne Klassenvariablen. Die Klasse wurde in folgenden Code umgesetzt:
public class Klasse {
protected int divide(int a, int b){
return a / b;
}
}
...
public static void main(String[] args){
Klasse cls = new Klasse();
cls.divide(10,20);
}
private

Die oben dargestellte UML Klasse zeigt zwei private Attribute und eine private Methode. Der Code dieser Klasse sieht wie folgt aus:
public class Klasse {
private int a;
private int b;
private int minus(){
return this.b - this.a;
}
}

Die im oberen Bild dargestelle Klasse wurde in folgenden Code umgewandelt:
public class Klasse {
private int count(int a, int b){
return b - a;
}
}
...
public static void main(String[] args){
//Instanzierung nur möglich wenn in der selben Klasse
Klasse cls = new Klasse();
//Aufruf nur möglich wenn in der selben Klasse
cls.count(10,20);abstrakten Klassen
}
Abstrakte Klassen und Methoden
Bei abstrakten Klassen (siehe Abstrakte Klasse) wird der Name kursiv geschrieben. Weiters werden auch die abstrakte Methoden kursiv geschrieben.
Schnittstellen
Eine Schnittstelle wird nahezu gleich wie eine Klasse dargestellt und zwar mit einem Rechteck. Der Unterschied ist aber, dass bei einer Schnittstelle das Rechteck mit dem Schlüsselwort <<interface>> gekennzeichnet wird.

Hier wird aus einem UML Klassendiagramm ein Programm erstellt:

In oberen Bild sieht man ein Interface mit mehreren Methoden. Diese Methoden werden von einer Klasse namens Rectangle implementiert. Die Programmierung zu diesen zwei Elementen sieht wie folgt aus:
Moveable.java
public interface Moveable {
int left(int x);
int right(int x);
int up(int y);
int down(int y);
int forwards(int z);
int backwards(int z);
}
Rectangle.java
public class Rectangle implements Moveable {
public int positionx;
public int positiony;
public int positionz;
@Override
public int left(int x) {
return positionx - x;
}
@Override
public int right(int x) {
return positionx + x;
}
@Override
public int up(int y) {
return positiony + y;
}
@Override
public int down(int y) {
return positiony - y;
}
@Override
public int forwards(int z) {
return positionz + z;
}
@Override
public int backwards(int z) {
return positionz - z;
}
}
Generalisierung
Durch eine Generalisierung erben speziellere Klassen von generelleren Klassen. Dadurch werden bestimmte Merkmale von der generellen Klasse an die spezialisierte Klasse vererbt. Die Pfeilspitze der Generalisierung zeigt auf die Oberklasse (Klasse von welcher geerbt wird).

Im Folgenden wird ein Beispiel zum besseren Verständnis von Generalisierungen gezeigt:

In dem oben dargestellten Bild sieht man eine Generalisierung zwischen einer abstrakten und einer normalen Klassen. Die Umsetzung in Java würde wie folgt aussehen:
Animal.java
package at.htldornbirn.awi3.swp3.animals;
public abstract class Animal {
private String habitat;
public Animal(String habitat) {
this.habitat = habitat;
}
public abstract void move();
public String getHabitat() {
return habitat;
}
}
Fuchs.java
package at.htldornbirn.awi3.swp3.animals;
public class Fuchs extends Animal {
public Fuchs() {
super("Woods/Forest");
}
@Override
public void move() {
System.out.println("Running round his " + getHabitat());
}
}
Assoziation
Eine Assoziation bezeichnet eine Beziehung zwischen zwei oder mehreren Klassen, wobei die häufigste Verbindung zwischen genau zwei Klassen aufritt. Es gibt folgende zwei Arten von Assoziationen:
N-äre Assoziation
In folgenden Bild sieht man eine Binäre Assoziation. (Binär, weil zwei Klassen miteinander verbunden wurden)

Reflexive Assoziation
Im hier dargestellten Bild sieht man eine reflexive Assoziation, welche auf sich selbst verweist.

Eigenschaften von Assoziationen
Da Assoziationen durch Linien dargestellt werden, müssen diese durch ein Assoziationsende gekennzeichnet werden. Diese Assoziationsenden können folgende Merkmale aufweisen:
- Sie können eine Multiplizität besitzen. Diese enthält Informationen über das Beziehungsverhältnis zweier Klassen. Diese Zahlen befinden sich nur im positiven und ganzzahligen Bereich, wobei der Beginn bei der Zahl 0 liegt.
- Multiplizitäten werden im folgenden Format angegeben:
untereSchranke..obereSchranke
- Bei * oder auch 0..* wird die untereSchranke als 0 und die obereSchranke als unendlich angenommen.
- Beide Schranken dürfen nicht 0 oder unbeschränkt sein. Falls beide Grenzen trotzdem gleich groß sind, wird nur die obereSchranke angegeben.
- Bei einer Multiplizität von 0..1 wird das Element als optional bezeichnet.
- Wenn die obereSchranke über dem Wert 1 liegt, wird das Element als mehrwertiges Element bezeichnet, da mehrere Wert annehmbar sind.
- Sie können Namen besitzen.
- Sie können eine Sichtbarkeit aufweisen.
- Es kann spezifiziert werden, ob das Assoziationsende ordered und/oder unique ist.
Zum Assoziationsende kommen oft Multiplizitäten hinzu, welche die Beziehung zwischen den zwei Instanzen regelt. Im folgenden wird auf zwei Arten der Assoziationen genauer eingegangen.
Tip um die Multiplizität korrekt zu bestimmen
Beispiel: Raum und Gebäude
Es kann immer folgende Frage gestellt werden:
Ein Raum ist in wievielen Gebäuden? In einem also kommt eine 1 zum Gebäude.
Ein Gebäude hat wieviele Räume? Einen oder mehrere also kommt ein 1..* zum Raum.
Komposition und Aggregation
Um Beziehungen mit Ganzen und Teilen darzustellen werden die Aggregation und die Komposition verwendet.
Komposition

Die graphische Darstellung einer Komposition ist eine Linie mit einer ausgefüllten Raute, welche mit der Kardinalität 1 beschriftet wird und mit dem Ganzen Teil der Beziehungspartner verbunden ist. Bei einer Komposition können die Teile nicht ohne das Ganze existieren. Das bedeutet, dass das Teil Element existenziell abhängig vom Ganz Element ist.
Aggregation
Die graphische Darstellung einer Aggregation ist eine Linie mit einer nicht ausgefüllten Raute, welche die Kardinalität 0..* besitzt und mit dem Ganzen Teil verbunden ist. Die Elemente in einer Aggregation besitzen keine Exisitenzabhängigkeit, da die Teil Elemente auch ohne die Ganz Elemente bestehen können.
Die Assoziationsarten werden prinzipiell mittels der Kardinalität unterschieden. Zudem sind die Teil Elemente Bestandteil genau eines Ganz Elementes, da sie NIE zu mehrere Ganz Elementen gehören.
Beispiel mit Umsetzung
Diese Umsetzung erfolgte mit der Programmiersprache Java.

Vehicle.java
package at.htldornbirn.swp4.hue2.vehicle;
public abstract class Vehicle {
private int maxSpeed;
private int wheels;
public Vehicle(int maxSpeed, int wheels) {
this.maxSpeed = maxSpeed;
}
public void move() {
System.out.println("I am moving at " + maxSpeed + " with " + wheels + " wheels.");
}
public int getMaxSpeed() {
return maxSpeed;
}
public abstract void start();
}
Bike.java
package at.htldornbirn.swp4.hue2.vehicle.unmotorized;
import at.htldornbirn.swp4.hue2.vehicle.Vehicle;
public class Bike extends Vehicle {
public Bike(int maxSpeed, int wheels) {
super(maxSpeed, wheels);
}
@Override
public void start() {
System.out.println("I start to step into the pedals!");
}
}
Rollerblades.java
package at.htldornbirn.swp4.hue2.vehicle.unmotorized;
import at.htldornbirn.swp4.hue2.vehicle.Vehicle;
public class Rollerblades extends Vehicle {
public Rollerblades(int maxSpeed) {
super(maxSpeed, 8);
}
@Override
public void start() {
System.out.println("I start skate!");
}
}
Skateboard.java
package at.htldornbirn.swp4.hue2.vehicle.unmotorized;
import at.htldornbirn.swp4.hue2.vehicle.Vehicle;
public class Skateboard extends Vehicle {
public Skateboard(int maxSpeed) {
super(maxSpeed, 4);
}
@Override
public void start() {
System.out.println("I step with one feet on the ground to start!");
}
}
MotorizedVehicle.java
package at.htldornbirn.swp4.hue2.vehicle.motorized;
import at.htldornbirn.swp4.hue2.vehicle.Vehicle;
public abstract class MotorizedVehicle extends Vehicle {
private float kw;
public MotorizedVehicle(int maxSpeed, int wheels, float kw) {
super(maxSpeed, wheels);
this.kw = kw;
}
@Override
public void start() {
System.out.println("I am starting my engine with " + kw + " kw.");
}
}
EBike.java
package at.htldornbirn.swp4.hue2.vehicle.motorized;
public class EBike extends MotorizedVehicle {
public EBike(int maxSpeed, float kw) {
super(maxSpeed, 2, kw);
}
}
Lkw.java
package at.htldornbirn.swp4.hue2.vehicle.motorized;
public class Lkw extends MotorizedVehicle {
public Lkw(int maxSpeed, int wheels, float kw) {
super(maxSpeed, wheels, kw);
}
}
Pkw.java
package at.htldornbirn.swp4.hue2.vehicle.motorized;
public class Pkw extends MotorizedVehicle {
public Pkw(int maxSpeed, float kw) {
super(maxSpeed, 4, kw);
}
}
Quellen
https://de.wikipedia.org/wiki/Klassendiagramm#Notation_in_der_Unified_Modeling_Language