1. Objektorientierung in der Anwendung
Softwareentwicklung läuft in mehreren Phasen:
Anforderungsanlyse: Was will der Kunde?
Architektur und Design: Modellierung der Software
Test und Implementierung: Realisierung und Implementierung
Dem zweiten Schritt wird oft zu wenig Aufmerksamkeit geschenkt. Viel zu schnell gehen Entwickler an die Tastatur und überlegen nicht, wie genau sie die Typen in Beziehung setzen.
Voraussetzungen
Besser Software modellieren können
Noch mehr Aufgaben findest du im Buch: ›Captain CiaoCiao erobert Java: Das Trainingsbuch für besseres Java. 300 Java-Workshops, Aufgaben und Übungen mit kommentierten Lösungen‹
1.1. Wiederholung vor Klassenhierachien und objektorientiertem Design
1.1.1. Kreise und Rechtecke modellieren ⭐
Implementiere eine Klasse
Circle
undRectangle
mit dendouble
-Eigenschaftenx
,y
für die Position und zusätzlich für Rechteckheight
,width
und für Kreisradius
vom Typdouble
.Die Attribute sollen privat sein, für die Attribute soll es Setter und Getter geben.
Schreibe eine Klasse
Application
, in dem immer alles ausprobiert werden kann.Implementiere für
Circle
undRectangle
eine Methodedouble area()
.Überschreibe die Methode
toString()
vonObject
, sodass die Kreise und Rechtecke sinnvolle Zeichenketten zurückgeben.Leite die Objekte von einer Oberklasse
Form
ab.Mache die Oberklasse abstrakt und
area()
ebenso.Implementiere eine Klasse
Group
, die einevoid add(Form form)
-Methode besitzt. Mit ihr soll man beliebigeForm
-Objekte im Container ablegen können. Intern soll der Container sich die Elemente in einerArrayList<Form>
halten.Schreibe im
Group
eine Methodedouble area()
, die über alle Formen summiert und die Gesamtfläche zurückgibt.Kann
Group
auchForm
erweitern? Was würde das bringen?Implementiere einen
FormSizeComparator
, der die SchnittstelleComparator
implementiert. Auf diese Weise soll derComparator
bei zwei beliebige Formen sagen können, welche Form größer, kleiner, oder ob die Formen sogar gleich groß sind.Implementiere in der Gruppe eine Methode
maximum()
, die die größte Form dieser Gruppe liefert. Die Methode liefertnull
, wenn die Gruppe leer ist. Greife intern aufCollections.max(…)
zurück.
1.1.2. Das Spiel des Lebens umsetzen ⭐⭐
Das Spiel des Lebens (engl. Conway’s Game of Life) ist ein vom Mathematiker John Horton Conway 1970 entworfenes System, basierend auf einem zweidimensionalen zellulären Automaten. Es ist eine einfache und bis heute populäre Umsetzung der Automaten-Theorie von Stanisław Marcin Ulam. (Zitat: Wikipedia). Studiere die https://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens#Die_Spielregeln.
Aufgabe:
Lege in einem Java-Programm ein zweidimensionales
boolean[][]
-Array frei wählbarer Größe an.Erzeuge zu Beginn ca. 30 % lebende Zellen in der Matrix.
Gib die Matrix auf der Konsole aus.
Wende die Spielregeln an und gib die Matrix wieder aus.
Repräsentiere das Spiel durch passende Klassen und Methoden.
Bonus: Erzeuge aus dem Spiel eine Grafik als GIF. Mache jede Zelle 2 x 2 Bildpunkte groß.
BufferedImage img = new BufferedImage( size, size, BufferedImage.TYPE_INT_ARGB );
img.setRGB( x, y, Color.BLACK.getRGB() );
ImageIO.write( img, "gif", new File("gol.gif") );
Bonus-Bonus: Kopiere die Klasse https://gist.github.com/jesuino/528703e7b1974d857b36 in den Workspace und generiere damit ein animiertes GIF mit mehreren Zell-Generationen.
1.1.3. FIGfont ⭐⭐⭐
Als Computer noch keine modernen Grafikkarten mit Pixeldarstellungen hatten, sondern nur Zeichen darstellen konnten, hat sich eine Kunstform gebildet, die bis heute anhält. Die Rede ist von ASCII-Art. Eine Unterform bilden große Schriften aus Buchstaben, Ziffern und Sonderzeichen. Ein Beispiel:
_/_ _/_ _ _ ___ (__(_(_(___(/_(_/_(_) .-/ (_/
Um diese ASCII-Schriften handelt die Aufgabe:
Gehe auf http://patorjk.com/software/taag/ und verstehe das Prinzip von FIGlet.
Ein FIGfont besteht aus Zeichen in ASCII-Text, ließ https://de.wikipedia.org/wiki/FIGlet-Font.
Studiere anschließend https://github.com/cmatsuoka/figlet/blob/master/fonts/big.flf und erkenne das Muster (die genaue Beschreibung ist unter https://github.com/cmatsuoka/figlet/blob/master/figfont.txt).
Kopiere eine FLF-Textdatei in das Java-Projektverzeichnis.
Schreibe ein Java-Programm, das eine beliebige Zeichenfolge mit dem Font auf der Kommandozeile ausgibt. Das Dateiformat muss nicht vollständig geparst werden, und nicht alle Zeichen müssen eingelesen werden, es reichen Buchstaben. Es ist akzeptabel, wenn das Programm auf genau diese FLF-Datei zugeschnitten ist.
Tipp: Alle Zeilen einer Datei liest man ein mit Files.readAllLines(Paths.get("big.flf"));
1.2. Kämpfer und Zauberer laufen über das Land
1.2.1. Kämpfer und Zauberer ⭐
Eine Klasse Warrior
und Wizard
sollen zwei Typen in einem Computerspiel sein. Beide haben
einen Namen,
eine Stärke (
int strength
) undeine Intelligenz (
int intelligence
).
Stärke und Intelligenz haben Wertebereiche von 0 bis 10. Überlege selbständig eine Vererbungsbeziehung.
Schreibe in Klasse Playground
mit main(…)
-Methode und baue zwei Krieger und zwei Zauberer auf.
1.2.2. Polymorphie und dynamisches Binden ⭐
Stärke und Intelligenz verbinden sich zu einer Spielstärke int getPower()
, wobei beim Warrior
gilt: strength * 2 + intelligence
und beim Wizard
: strength + intelligence * 2
. Ganz mathematisch soll das ganze nicht sein, das Ergebnis soll eine zufällige Schwankung von 20% aufweisen (nach oben und unten).
Lasse die vier Typen gegeneinander antreten und schaue, wer gewinnt.
1.2.3. Einfache 1:n Assoziationen durch Datenstrukturen ⭐
Eine Landkarte besteht auch 20 x 20 "Kacheln". Jede Kachel kann einen Typ haben, etwa Acker, Wasser, Wiese oder andere. Wie kann man das ausdrücken?
Zwei Spieler sollen auf der Landkarte stehen und die Spieler sollen über Methoden bewegt werden können. Auf dem Wasser stehen ist nicht möglich.
An der Klasse für die Landkarte soll eine Methode setActionOnPlayerCollision(PlayerCollision)
zu finden sein; PlayerCollision
ist eine Schnittstelle mit einer Operation onCollision(/Typ?/ player1, /Typ/ player2)
, die immer dann aufgerufen wird, wenn ein Spieler so bewegt wird, dass er mit einem anderen Spieler zusammentrifft. Eine Implementierung der Schnittstelle soll nun einen Kampf beginnen und ausgeben, welcher der beiden Spieler gewinnen würde.
1.3. Idiome, Clean-Code und Design-Pattern
Design-Pattern (Entwufsmuster auf Deutsch) sind Best-Practises, um Software flexibel zu modellieren. Bekannt wurde Design-Pattern durch ein Buch, doch heute sind viele weitere Muster beschrieben.
1.3.1. Das meldende Schiff ⭐⭐
Einem Schiff können Elektrogeräte hinzugefügt werden. Immer dann, wenn die Hinzufügemethode aufgerufen wird, soll ein Ereignis ausgelöst werden. Die Interessenten für das Ergebnis melden sich am Schiff an und werden immer dann informiert, wenn ein neues Elektrogerät in das Schiff kommt.
Ship bude = new Ship();
ElectronicDevice radio = new Radio();
ElectronicDevice tv = new TV();
bude.addModificationListener( .... );
bude.add( radio ); // Meldung vom Listener
bude.add( tv ); // Meldung vom Listener
1.3.2. Formeln ⭐⭐
Gesucht ist eine Modellierung, mit der man Formeln im Speicher als Objektbaum repräsentieren kann. Die Formeln können zusammengesetzt sein aus
Literalen (mit Operatoren),
geklammerten Ausdrücken,
Brüchen,
Wurzeln,
Exponenten.
Die Modellierung sollte allgemein sein, sodass sich beliebige Ausdrücke mit Brüchen und Wurzeln, etc. darstellen und auch schachteln lassen. Es geht nicht um die Darstellung! Gib den Typen eine einfache toString()
-Methode.
Repräsentiere zum Testen der API folgende Formeln: