Frage zu Decorator-Pattern

videlius

Mitglied
Hallo,

ich beschäftige mich gerade mit dem Decorator-Designpattern.
Dazu hab ich mir ne kleine Anwendung geschrieben.
Das Beispiel gibts auch im Netz.

//Das Food-Interface

Java:
public interface Food {

    public String getDescription();
    public double getPrize();
}

//Eine konkrete Implementation von Food

Java:
public class Schnitzel implements Food {

    private double temperature = 20;

    public String getDescription() {
       return "Schnitzel";
    }

    public double getPrize() {
        return 10.50;
    }
    
    public double getTemperature()
    {
        return temperature;
    }

    public double erwaermen(double newTemp)
    {
        temperature = newTemp;
    }

}

//Der abstrakte Decorator

Java:
public abstract class FoodDecorator implements Food {

    final Food food;

    public FoodDecorator(Food food) {
        this.food = food;
    }
}

//ein konkreter Decorator

Java:
public class Kartoffeln extends FoodDecorator{

    public Kartoffeln(Food food) {
        super(food);
    }



    public String getDescription() {
        return food.getDescription() + " und Kartoffeln";
    }

    public double getPrize() {
        return food.getPrize() + 1.50;
    }


}

//Die main

Java:
    public static void main(String[] args) {
        Food dinner = new Schnitzel();
        dinner = new Kartoffeln(dinner);

        System.out.println(dinner.getDescription());
        System.out.println("Preis: "+dinner.getPrize()+"€");

    }

Das klappt soweit ganz gut.
Ausgabe:

Code:
Schnitzel und Kartoffeln
Code:
Preis: 12.0€


Soweit so gut.
Jetzt hätte ich aber auch gerne die Temperatur des Schnitzels ausgegeben.
Dazu müsste ich ja die "getTemperature()"-Methode von Schnitzel ebenfalls im Interface definieren.
Das hätte aber zur Folge das jeder konkrete Decorator, also auch Kartoffeln, diese Methode implementieren muss, obwohl dass keinen Sinn macht.

Gibt es eine Möglichkeit direkt auf die Methoden der Basisklasse zuzugreifen um eben z.B. die Temperatur zu erfahren, oder aber auch Variablen der Basisklasse zu verändern (erwaermen), oder ist dieses Pattern an der Stelle ungeeignet?
 
Du könntest im Interface die Methode definieren, dann eine abstracte Basisklasse für dieses Interface machen und dort generell die interne Methode aufrufen. Dann leitest du deine Decoratoren von der Basisklasse ab.
 
Also wenn ich das richtig verstehe, soll ich in der Klasse FoodDecorator alle Methoden der Basisklasse (Schnitzel) aufrufen.

Dazu muss ich sagen, dass ich das Decorator-Pattern in ein von mir geschriebenes Programm einbauen möchte. In diesem Programm hat die Basisgerichtklasse gleich mal 10 Methoden und erbt noch zusätzlich von Rectangle2D. Ich müsste also alle Methoden die ich jemals benutze sowohl in das Interface als auch in die abstrakte Decoratorklasse eintragen. Außerdem müsste ich Code an zwei weiteren Stellen ändern wenn ich der Basisklasse eine neue Methode hinzufügen möchte.

Das erscheint mir unpraktikabel.

Ich hab mir mal das überlegt:

// in der Klasse FoodDecorator habe ich eine Getter-Methode für meine Variable food eingebaut

[Java]
abstract class FoodDecorator implements Food {

final Food food;

public FoodDecorator(Food food) {
this.food = food;
}

public Schnitzel getBaseFood() {
return (Schnitzel) food;
}

}
[/Java]



// Beim Aufruf in der Main-Klasse komme ich über die Variable an die Methoden des Basisgerichts heran


[Java]
...
if (dinner instanceof FoodDecorator) {
FoodDecorator tmp = (FoodDecorator) dinner;
System.out.println("Temperatur: " + tmp.getBaseFood().getTemperature());
tmp.getBaseFood().erwaermen(56.3);
System.out.println("neue Temperatur: " + tmp.getBaseFood().getTemperature());
...
[/Java]

Zumindest geht es:

Code:
Schnitzel und Kartoffeln
Code:
Preis: 12.0€
Code:
Temperatur: 20.0
Code:
neue Temperatur: 56.3

Wäre das prinzipiell eine Möglichkeit oder verstößt das gegen Programmierregeln bzw. ist das schlechter Programmierstil?
 
kann man natürlich aber gerade das bringt ja den Effect des Decorators wieder weg. Wieso implementieren so Klassen wie Schnitzel und Foo eigentlich nicht gleich das Interface Food?
 

Zurück
Oben