2016-03-30 11 views
2

Gegeben das klassische Kaffeedekoratorbeispiel (kopiert von Wikipedia).Wohin man die Variablen der gemeinsamen Mitglieder in Dekoratoren setzt

public interface Coffee { 
    public double getCost(); 
} 

public class SimpleCoffee implements Coffee { 
    public double getCost() { 
     return 1; 
    } 
} 

public abstract class CoffeeDecorator implements Coffee { 
    protected final Coffee decoratedCoffee; 
    public CoffeeDecorator(Coffee c) { 
     this.decoratedCoffee = c; 
    } 
    public double getCost() { 
     return decoratedCoffee.getCost(); 
    } 
} 

class WithMilk extends CoffeeDecorator { 
    public WithMilk(Coffee c) { 
     super(c); 
    } 
    public double getCost() { 
     return super.getCost() + 0.5; 
    } 
} 

sagen Lassen Sie jetzt den Preis aller Dekorateure (zum Beispiel Milch) auf einige Attribut abhängig, dass alle Kaffeesorten (etwa die Größe des Kaffee) haben wird, und dass die Größe der Kaffee wird nie an anderer Stelle verwendet. Wo sollte die Kaffeegröße zur Klassenhierarchie hinzugefügt werden?

ich es in der Coffee-Schnittstelle setzen kann

public interface Coffee { 
    public double getCost(); // Returns the cost of the coffee 
    public/protected double size; 
} 

Wenn es für den öffentlichen gesetzt ist, wird die Größe unnötig ausgesetzt

Wenn es geschützt gesetzt ist, können Dekorateure nicht wirklich durch decoratedCoffee zugreifen (siehe diesen Beitrag Java: cannot access a protected member of the superclass in the extending subclass und Why can't a derived class call protected member function in this code?)

ich es in CoffeeDecorator setzen können, aber dann hätte ich ändern den Konstruktor zu

public CoffeeDecorator(Coffee c) { 
    if c is of type CoffeeDecorator 
     size = c.size; 
    this.decoratedCoffee = c; 
} 

die irgendwie nicht wie die eleganteste Lösung scheint ... (offensichtlich durch die Kette von decoratedCoffee s graben, bis ich eines mit Nicht-Null-Größe zu finden, ist keine Option)

Ich kann setzen es in jedem Dekorateur, der gerade gegen die Design-Prinzipien verstößt.

Ich bin ziemlich sicher, dass dieses Szenario ziemlich oft auftaucht, würde ich gerne wissen, was ist der beste Weg, um solche Fälle zu behandeln?

Vielen Dank im Voraus.

--- bearbeitet 31/3/2016 ---

Clarify, dass das bestimmte Attribut (vorher Größe Tasse, jetzt umbenannt zu Kaffee Größe) ist etwas, das alles Kaffees haben sollte.

Antwort

0

Ich denke nicht, dass das Hinzufügen der Cup-Größe in eine dieser Klassen eine gute Idee ist. Es passt da einfach nicht rein, weil der Kaffee nichts über Tassen weiß.

Die Cup kann eine separate Klasse (theat Code als Pseudo-Code, ich bin mit Java-Syntax nicht sehr vertraut) sein:

public class Cup { 
    private Coffee coffee; 

    public Cup(Coffee c) { 
     this.coffee = c; 
    } 

    public getCost() { 
     return this.getSize() * c.getCost(); 
    } 

    public getSize() { 
     return 1; // standard cup 
    } 
} 

public class BigCup extends Cup { 

    public getSize() { 
     return 2; // double size 
    } 

} 

So, jetzt können Sie new BigCup(new WithMilk(new Coffee())) tun. Alternativ kann die Cup auch ein Dekorateur sein, macht es Sinn, in der Programmierung, aber vielleicht in Bezug auf dem wirklichen Leben ein bisschen weniger Sinn (weil jetzt auch der Cup Coffee implementiert, klingt lustig):

public class Cup extends CoffeeDecorator { 

    public Cup(Coffee c) { 
     super(c); 
    } 

    public getCost() { 
     return this.getSize() * super.getCost(); 
    } 

    public getSize() { 
     return 1; // standard cup 
    } 
} 

public class BigCup extends Cup { 

    public getSize() { 
     return 2; // double size 
    } 

} 
+0

Vielleicht Kaffee Größe wäre ein besserer Begriff, der Schlüssel ist, dass die Dekorateure auf "einige Attribute", die in allen Kaffees vorhanden ist, werde ich klären – Woofas

+0

@Woofas, die noch nicht klar ist, was bedeutet "Kaffee Größe" bedeuten? Und wie genau sind die Dekorateure davon abhängig? Und warum können Sie es nicht genauso hinzufügen wie 'getCost()' (irgendeine 'getSize()' Methode) oder, noch besser, stellen Sie dieses Attribut überhaupt nicht zur Verfügung und sagen ([tell, do not ask] (http://martinfowler.com/bliki/TellDontAsk.html)) 'Coffee' Objekt etwas zu tun, abhängig von dieser' Größe'? Im Allgemeinen sieht das Beispiel mit "Kaffee-Größe" immer noch nicht realistisch aus, daher ist nicht klar, was genau das Problem ist. –

Verwandte Themen