Given the classic coffee decorator example (copied from Wikipedia).
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;
}
}
Let's say now the price of all decorators (e.g. Milk) depends on some attribute that all coffees will have (say the size of the coffee) and that the size of coffee is NEVER used elsewhere. Where should add coffee size to the class hierarchy?
I can put it in the Coffee Interface
public interface Coffee {
public double getCost(); // Returns the cost of the coffee
public/protected double size;
}
If it's set to public, the size is unnecessarily exposed
If it's set to protected, decorators can't really access it through decoratedCoffee (see this post Java: cannot access a protected member of the superclass in the extending subclass and Why can't a derived class call protected member function in this code?)
I can put it in CoffeeDecorator, but then I would have to modify the constructor to
public CoffeeDecorator(Coffee c) {
if c is of type CoffeeDecorator
size = c.size;
this.decoratedCoffee = c;
}
Which somehow doesn't seem like the most elegant solution... (Obviously digging through the chain of decoratedCoffee
s until I find one with non-null size is not an option either)
I can put it in each decorator which just goes against the design principles.
I'm pretty sure this scenario comes up quite often, I'd like to know what is the best way of handling such case?
Thanks in advance.
--- Edit 31/3/2016 ---
Clarify that the certain attribute (previously cup size, now renamed to coffee size) is something that all coffees should have.