Programmieren in Java Vorlesung 04: Rekursive Klassen

Prof. Dr. Peter Thiemann Albert-Ludwigs-Universit¨ at Freiburg, Germany

SS 2015

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

1 / 56

Inhalt Verkettete Listen Unver¨anderliche Daten Entwurf von Methoden auf Listen Arithmetische Ausdr¨ ucke Entwurf von Methoden auf Ausdr¨ ucken Erweiterung I: Neue Art von Ausdruck hinzuf¨ ugen Erweiterung II: Neue Operation hinzuf¨ ugen Adventure Decorator Template-Methode Beispiele f¨ ur Anwendung des Decorator

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

2 / 56

Executive Summary — Rekursive Klassen

1. Datenmodellierung I I I

Unver¨anderliche Daten (Immutable Data) Verkettete Listen Arithmetische Ausdr¨ ucke

2. Methodenentwurf auf rekursiven Klassen I I I I

Rekursive Methoden Composite Pattern Decorator Pattern Template Method

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

3 / 56

Rekursive Klassen I I

Eine Klasse ist rekursiv, falls sie eine rekursive Assoziation besitzt. Eine Assoziation ist rekursiv, falls sie von einer Klasse zur gleichen Klasse, einer Superklasse oder einem implementierten Interface f¨ uhrt.

Beispiele

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

4 / 56

Verkettete Listen

Verkettete Listen

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

5 / 56

Verkettete Listen

Verkettete Listen von Zahlen

I

Typ der Elemente instanziert zu int

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

6 / 56

Verkettete Listen

Verkettung der Objekte

1

new ConsInt (1, new ConsInt (4, new ConsInt (9, new NilInt())))

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

7 / 56

Verkettete Listen

Verkettete Liste in Java 1

public interface IListInt { }

1

public class NilInt implements IListInt { }

1 2 3 4 5 6 7 8 9

public class ConsInt implements ConsInt { private final int element; private final IList rest; public ConsInt (int element, IList rest) { if (rest == null) throw new IllegalArgumentException(”rest of list must not be null”); this.element = element; this.rest = rest; }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

8 / 56

Verkettete Listen

Unver¨ anderliche Daten

Einschub: Unver¨anderliche Daten I

Es ist oft vorteilhaft, wenn die Felder von Objekten unver¨ anderlich sind (“immutable”).

I

Erreicht durch Deklaration aller Felder als final (vgl. ConsInt). Vorteile

I

I

Ein immutable Objekt verh¨alt sich immer gleich bez¨ uglich equals() und hashCode().

I

I I

I

Invarianten des Objekts m¨ ussen nur vom Konstruktor kontrolliert werden. Ein immutable Objekt muss nicht kopiert werden. Nebenl¨aufiges Programmieren wird einfacher, wenn viele Objekte immutable sind.

Nachteile I

Ggf. geringe Einbußen der Performance

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

9 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Entwurf von Methoden auf Listen

I int length();

L¨ange einer Liste I int sum();

Summe der Elemente einer Liste I IListInt append (IListInt other);

Verketten der Liste mit other

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

10 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Erweitern des Interface (Composite Pattern)

1 2 3 4 5

public interface IListInt { int length(); int sum(); IListInt append(); }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

11 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Entwurf von Methoden auf Listen L¨ ange einer Liste: int length();

Leere Liste Die leere Liste (NilInt) hat L¨ange 0. 1

new NilInt ().length() == 0

Implementierung 1 2 3 4 5 6

public class NilInt implements IListInt { int length() { return 0; } //... }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

12 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Entwurf von Methoden auf Listen L¨ ange einer Liste: int length();

Nichtleere Liste Eine nicht-leere Liste (ConsInt) hat L¨ange 1 plus L¨ange der Restliste. 1 2

new ConsInt(51, new NilInt ()).length() == 1 new ConsInt(42, new ConsInt(51, new NilInt ())).length() == 2

Implementierung 1 2 3 4 5 6

public class ConsInt implements IListInt { int length() { return 1 + rest.length(); } //... }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

13 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Entwurf von Methoden auf Listen Summe einer Liste: int sum();

Leere Liste Die leere Liste (NilInt) hat Summe 0. 1

new NilInt ().sum() == 0

Implementierung 1 2 3 4 5 6

public class NilInt implements IListInt { int sum() { return 0; //... } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

14 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Entwurf von Methoden auf Listen Summe einer Liste: int sum();

Nichtleere Liste Eine nicht-leere Liste (ConsInt) hat als Summe ihr Element plus Summe der Restliste. 1 2

new ConsInt(51, new NilInt ()).sum() == 51; new ConsInt(42, new ConsInt(51, new NilInt ())).sum() == 93;

Implementierung 1 2 3 4 5 6

public class ConsInt implements IListInt { int sum() { return this.element + rest.sum(); //... } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

15 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Entwurf von Methoden auf Listen Listenverkettung: IListInt append(IListInt other);

Leere Liste Verketten der leeren Liste (NilInt) mit other ist other. 1

new NilInt ().append(other) == other

Implementierung 1 2 3 4 5

public class NilInt implements IListInt { IListInt append(IListInt other) { return other; } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

16 / 56

Verkettete Listen

Entwurf von Methoden auf Listen

Entwurf von Methoden auf Listen Listenverkettung: IListInt append(IListInt other);

Nichtleere Liste Verketten einer nicht-leeren Liste (ConsInt) mit other liefert eine nicht-leere Liste mit gleichem ersten Element und als Restliste: die Verkettung der urspr¨ unglichen Restliste mit other. 1 2

new ConsInt(51, new NilInt ()).append(other) .equals (new ConsInt(51, ( new NilInt ().append(other) ) ));

3 4 5

new ConsInt(42, new ConsInt(51, new NilInt ())).append(other) .equals (new ConsInt(42, ( new ConsInt(51, new NilInt ()).append(other) ) ));

Implementierung 1 2 3 4 5 6

public class ConsInt implements IListInt { IListInt append(IListInt other) { return new ConsInt(this.element, rest.append(other)); } // ... } Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

17 / 56

Verkettete Listen

Komplette Implementierung 1 2 3 4 5 6 7 8 9 10 11 12 13 14

Entwurf von Methoden auf Listen

NilInt

public class NilInt implements IListInt { // empty list has length 0 int length() { return 0; } // empty list has sum 0 int sum() { return 0; } // empty list appended to other is other IListInt append(IListInt other) { return other; } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

18 / 56

Verkettete Listen

Komplette Implementierung 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Entwurf von Methoden auf Listen

ConsInt

public class ConsInt implements IListInt { // constructor and fields omitted // length is 1 plus length of rest int length() { return 1 + rest.length(); } // sum is element plus sum of rest int sum() { return element + rest.sum(); } // Cons(element, rest) appended to other reconstructs the element // around rest appended to other IListInt append(IListInt other) { return new ConsInt(element, rest.append(other)); } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

19 / 56

Arithmetische Ausdr¨ ucke

Arithmetische Ausdru¨cke

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

20 / 56

Arithmetische Ausdr¨ ucke

Verwendung von B¨aumen

I

Listen und B¨aume werden oft verwendet um abstrakte Datentypen effizient zu implementieren

I

In diesen Anwendungen ist die Struktur ein Hilfsmittel um Effizienz zu erreichen

I

Es gibt auch Anwendungen, wo die Baumstruktur ein essentieller Teil des Datenmodells ist

I

Paradebeispiel daf¨ ur sind arithmetische Ausdr¨ ucke

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

21 / 56

Arithmetische Ausdr¨ ucke

Arithmetische Ausdr¨ucke

Datenmodell Ein arithmetischer Ausdruck ist entweder I

eine Konstante (eine ganze Zahl) Beispiele: 0, 51, −42

I

eine Summe von zwei arithmetischen Ausdr¨ ucken Beispiele: 3+4, 17+4, 17+ (2+2)

Operation I

Der Wert eines arithmetischen Ausdrucks (eine ganze Zahl)

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

22 / 56

Arithmetische Ausdr¨ ucke

Klassendiagramm: Arithmetische Ausdr¨ucke Modellierung mit Composite Pattern

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

23 / 56

Arithmetische Ausdr¨ ucke

Java: Ger¨ust f¨ur arithmetische Ausdr¨ucke 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

public interface IExpr { int value(); } public class Const implements IExpr { private final int v; public Const (int v) { this.v = v; } // ... method implementations } public class Add implements IExpr { private finale IExpr left, right; public Add(IExpr left, IExpr right) { this.left = left; this.right = right; } // ... method implementations } Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

24 / 56

Arithmetische Ausdr¨ ucke

Methodenentwurf

I

new Const(42).value() == 42

Implementierung public class Const implements IExpr { // fields and constructor ... public int value() { return this.v; }

1 2 3 4 5 6

Const.value()

Der Wert einer Konstanten ist die Konstante selbst.

1

I

Entwurf von Methoden auf Ausdr¨ ucken

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

25 / 56

Arithmetische Ausdr¨ ucke

Methodenentwurf I

1 2 3

I

Add.value()

Der Wert eines Add Ausdrucks ist die Summe der Werte seiner Teilausdr¨ ucke. new Add(new Const (17), new Const (4)).value() == 21; new Add(new Const (17), new Add (new Const (2), new Const (2))).value() == 21;

Implementierung public class Add implements IExpr { // fields and constructor ... public int value() { return this.left.add() + this.right.add(); }

1 2 3 4 5 6

Entwurf von Methoden auf Ausdr¨ ucken

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

26 / 56

Arithmetische Ausdr¨ ucke

Erweiterung I: Neue Art von Ausdruck hinzuf¨ ugen

Erweiterung I: Neue Art von Ausdruck hinzuf¨ugen

Erweitertes Datenmodell Ein arithmetischer Ausdruck ist entweder I

eine Konstante (eine ganze Zahl) Beispiele: 0, 51, −42

I

eine Summe von zwei arithmetischen Ausdr¨ ucken Beispiele: 3+4, 17+4, 17+ (2+2)

I

ein Produkt von zwei arithmetischen Ausdr¨ ucken Beispiele: 3∗4, 2 ∗ (17+4), (2 ∗ 3) ∗ 4

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

27 / 56

Arithmetische Ausdr¨ ucke

Erweiterung I: Neue Art von Ausdruck hinzuf¨ ugen

Erweiterung I: Neue Art von Ausdruck Zum Hinzuf¨ ugen einer neuen Art von Ausdruck muss nur eine neue Klasse definiert werden, die das Interface IExpr implementiert. 1 2 3 4 5 6 7 8 9 10

class Product implements IExpr { private final IExpr left, right; public Product (IExpr left, IExpr right) { this.left = left; this.right = right; } // value is product of factors public int value() { return this.left.value() ∗ this.right.value(); } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

28 / 56

Arithmetische Ausdr¨ ucke

Erweiterung I: Neue Art von Ausdruck hinzuf¨ ugen

Beispiele mit Produkt

1 2 3

new Product (new Const (3), new Const (4)) . value() == 12; new Product (new Const (2), new Add (new Const (17), new Const (4))) . value() == 42;

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

29 / 56

Arithmetische Ausdr¨ ucke

Erweiterung II: Neue Operation hinzuf¨ ugen

Erweiterung II: Neue Operation hinzuf¨ugen

Erweitertes Aufgabenstellung Ein arithmetischer Ausdruck kann I

mit value() seinen Wert berechnen;

I

mit size() seine Gr¨oße berechnen. Die Gr¨ oße eines arithmetischen Ausdrucks ist die Anzahl der Operatoren und Konstanten.

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

30 / 56

Arithmetische Ausdr¨ ucke

Erweiterung II: Neue Operation hinzuf¨ ugen

Erweiterung II: Neue Operation hinzuf¨ugen Was ist zu tun? I 1 2 3 4

I

Interface anpassen public interface IExpr { int value(); int size(); }

In jeder Klasse, die das Interface implementiert, muss die neue Methode size() hinzugef¨ ugt werden

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

31 / 56

Arithmetische Ausdr¨ ucke

Erweiterung II: Neue Operation hinzuf¨ ugen

Erweiterung II: Neue Operation hinzuf¨ugen Was ist zu tun? I

Interface anpassen public interface IExpr { int value(); int size(); }

1 2 3 4

I

In jeder Klasse, die das Interface implementiert, muss die neue Methode size() hinzugef¨ ugt werden

Nachteil I

¨ Die Anderung ist nicht lokal.

I

Es m¨ ussen ggf. viele Klassen angepasst werden.

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

31 / 56

Arithmetische Ausdr¨ ucke

Methodenentwurf

I

new Const(42).size() == 42

Implementierung public class Const implements IExpr { // fields and constructor ... public int size() { return 1; }

1 2 3 4 5 6

Const.size()

Die Gr¨ oße einer Konstanten ist 1.

1

I

Erweiterung II: Neue Operation hinzuf¨ ugen

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

32 / 56

Arithmetische Ausdr¨ ucke

Methodenentwurf I

1 2 3

I

Add.size()

Die Gr¨ oße eines Add Ausdrucks ist die Summe der Gr¨oßen seiner Teilausdr¨ ucke plus 1 f¨ ur die Addition. new Add(new Const (17), new Const (4)).size() == 3; new Add(new Const (17), new Add (new Const (2), new Const (2))).size() == 5;

Implementierung public class Add implements IExpr { // fields and constructor ... public int size() { return 1 + this.left.size() + this.right.size(); }

1 2 3 4 5 6

Erweiterung II: Neue Operation hinzuf¨ ugen

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

33 / 56

Arithmetische Ausdr¨ ucke

Methodenentwurf I

1 2 3

I

Product.size()

Die Gr¨ oße eines Product Ausdrucks ist die Summe der Gr¨oßen seiner Teilausdr¨ ucke plus 1 f¨ ur die Multiplikation. new Product(new Const (17), new Const (4)).size() == 3; new Add(new Const (17), new Product (new Const (2), new Const (2))).size() == 5;

Implementierung public class Product implements IExpr { // fields and constructor ... public int size() { return 1 + this.left.size() + this.right.size(); }

1 2 3 4 5 6

Erweiterung II: Neue Operation hinzuf¨ ugen

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

34 / 56

Adventure

Das Decorator Pattern

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

35 / 56

Adventure

Adventure

Neue Anforderung Ein Monster kann w¨ahrend des Spiels unterschiedliche Eigenschaften erhalten und wieder ablegen. Zum Beispiel kann es verflucht sein (dann schl¨agt es h¨arter zu), es kann schl¨afrig sein (dann ist es langsamer), oder es kann unsichtbar sein.

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

36 / 56

Adventure

Decorator

Modellierung mit Decorator Pattern

Idee des Decorator Pattern I

Jede Eigenschaft/Modifikation wird durch eine eigene Decorator-Klasse repr¨asentiert.

I

Jedes Decorator-Objekt verweist auf das Objekt vor der Modifikation.

I

Die Operationen der Decorator-Klasse k¨ onnen ein ver¨andertes Verhalten implementieren und/oder die entsprechende Operation auf dem Objekt vor der Modifikation aufrufen (delegieren).

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

37 / 56

Adventure

Decorator

Erweitertes Monster-Interface: Name 1 2 3 4 5

public interface IMonster { // ... // return the monster’s name String name (); }

Beispielhafte Implementierung in Troll 1 2 3 4 5 6

public class Troll extends AMonster { // ... public String name() { return ”Troll’’; } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

38 / 56

Adventure

Template-Methode

Template-Methode Die Methode name() wird als Template-Methode verwendet, d.h. I

Sie wird in AMonster verwendet.

I

Sie bleibt abstrakt in AMonster (d.h. wird nicht implementiert).

I

Sie wird nur in konkreten Subklassen (von AMonster) implementiert.

Effekt: Verwendung von name() in AMonster ist konfigurierbar durch die konkreten Subklassen. 1 2 3 4 5 6 7 8 9 10

public abstract class AMonster implements IMonster { // ... // only implemented in concrete subclasses public abstract String name(); // ... but used right here: public boolean hit(int force) { System.out.println (”You hit the ” + name() + ”!”); return true; } } Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

39 / 56

Adventure

Template-Methode

Klassendiagramm: Monster mit Eigenschaften Modellierung mit Decorator Pattern

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

40 / 56

Adventure

Template-Methode

Klassendiagramm: Decorator Pattern Allgemeine Struktur

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

41 / 56

Adventure

Template-Methode

Java: Monster mit Eigenschaften 1 2 3

public abstract class AMonsterDecoration implements IMonster { // reference to original monster private final IMonster monster;

4

protected AMonsterDecoration(IMonster monster) { this.monster = monster; } // delegate method to original monster public boolean hit(int force) { return monster.hit(force); } // delegate method to origin public String name() { return monster.name(); }

5 6 7 8 9 10 11 12 13 14 15 16

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

42 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Der verfluchte Decorator

1 2 3 4

public class CursedDecoration extends AMonsterDecoration { protected CursedDecoration(IMonster monster) { super(monster); }

5

public String name() { return ”cursed ” + super.name(); }

6 7 8 9

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

43 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Der verfluchte Decorator — Beispiele

1 2 3 4

IMonster m = new Troll(); m.name(); // returns: ”Troll” m = new CursedDecoration (m); m.name(); // returns: ”cursed Troll”

5 6 7 8 9

IMonster d = new Dragon(); d.name(); // returns: ”Dragon” d = new CursedDecoration (d); d.name(); // returns: ”cursed Dragon’’

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

44 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Der unsichtbare Decorator

1 2 3 4

public class InvisibleDecoration extends AMonsterDecoration { protected InvisibleDecoration(IMonster monster) { super(monster); }

5

public String name() { return ”invisible monster”; }

6 7 8 9

}

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

45 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Der unsichtbare Decorator — Beispiele

1 2 3 4 5 6

IMonster m = new Troll(); m.name(); // returns: ”Troll” m = new InvisibleDecoration (m); m.name(); // returns: ??? m = new CursedDecoration (m); m.name(); // returns: ???

7 8 9 10 11 12 13

IMonster d = new Dragon(); d.name(); // returns: ”Dragon” d = new CursedDecoration (d); d.name(); // returns: ??? d = new InvisibleDecoration (d); d.name(10); // returns: ???

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

46 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Decorator vs Template Method — Probleme

1 2 3 4 5 6

IMonster m = new Troll(); m.hit(10); // output: You hit the Troll! m = new InvisibleDecoration (m); m.hit(10); // output: ??? m = new CursedDecoration (m); m.hit(10); // output: ???

7 8 9 10 11 12 13

IMonster d = new Dragon(); d.hit(10); // output: You hit the Dragon! d = new CursedDecoration (d); d.hit (10); // output: ??? d = new InvisibleDecoration (d); d.hit(10); // output: ???

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

47 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Warum Template Method funktioniert

1. Aufruf von hit() auf m1 startet Code in AMonster 2. F¨ uhrt zu Aufruf von name() auf demselben Objekt m1 Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

48 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Warum Decorator funktioniert

1. Aufruf von name() auf Decoration d1 started Code in CursedDecoration. 2. Dieser ruft name() auf dem Troll-Objekt m1 auf. (Wie gewollt) Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

49 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Warum Decorator + Template Method nicht funktioniert

1. Aufruf von hit() auf d1 startet Code in AMonsterDecoration. 2. Dieser leitet weiter an hit() auf dem Troll-Objekt m1. 3. Dieser ruft name() auf demselben Objekt auf und ignoriert somit die Decoration! Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

50 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Problem: Object Schizophrenia“ ”

I

Das schlechte Zusammenwirken von Decorator und Template Method ist ein Fall von Object Schizophrenia“. ” O.S. tritt auf, wenn die Funktionalit¨at eines Objektes in der Implementierung auf mehrere Objekte verteilt ist (Hier: Decorations und eigentliches Objekt)

I

In einem solchen Fall spricht man von Objektkomposition.

I

Sie tritt meist zusammen mit Delegation auf.

I

Delegation bedeutet, dass Methodenaufrufe unver¨andert von einem Objekt an ein anderes weitergereicht werden. Vgl. AMonsterDecoration.hit()

I

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

51 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

L¨osungsans¨atze

1. Decorator und Template Method nicht zusammen benutzen. 2. F¨ uge eine weitere Methode hinzu, die sich den urspr¨ unglichen Empf¨anger der Methode hit() merkt (also den Eintrittspunkt in die Objektkomposition).

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

52 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Zusammenf¨ugen von Decorator und Template Method I

I 1 2 3 4 5 6 7 8 9 10 11

Das Empf¨angerobjekt des ersten Eintritts in das komponierte Objekt muss erhalten bleiben. Also wird dieses Objekt als weiterer Parameter mitgegeben! public abstract class AMonster { // external interface; delegate to internal method // final = do not override public final boolean hit(int force) { return hit(force, this); // remember initial receiver } // internal interface; standard implementation for all monsters protected boolean hit(int force, AMonster receiver) { System.out.println (”You hit the ” + receiver.name() + ”!”); return true; }

12

public abstract String name();

13 14

} Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

53 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Der abstrakte Decorator

1 2 3 4 5 6 7 8 9 10

I

Standardm¨aßig delegiert ein Decorator die Methoden hit() und name().

I

Hier: Delegation bedeutet den Aufruf der gleichen Methode mit den gleichen Parametern auf dem previous Objekt. public abstract class AMonsterDecoration extends AMonster { private AMonster previous; // ... protected boolean hit(int force, AMonster receiver) { return previous.hit (force, receiver); } public String name() { return previous.name(); } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

54 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Konkreter Decorator

I 1 2 3 4 5 6 7 8 9

Modifiziert nur das Verhalten von name().

public class CursedDecoration extends AMonsterDecoration { protected CursedDecoration(AMonster monster) { super(monster); } @Override public String name() { return ”cursed ” + super.name(); } }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

55 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Klassendiagramm Decorator + Template Method

I

NB: + bedeutet public; ] bedeutet protected; − bedeutet private

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

56 / 56

Adventure

Beispiele f¨ ur Anwendung des Decorator

Fragen?

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

57 / 56