鉴于经典的咖啡装饰示例(从维基百科复制而来)。
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;
}
}
现在假设所有装饰者(例如牛奶)的价格取决于所有咖啡将具有的某些属性(比如咖啡的大小)以及咖啡的大小从未在其他地方使用过。应该将咖啡大小添加到类层次结构中?
我可以把它放在咖啡界面
public interface Coffee {
public double getCost(); // Returns the cost of the coffee
public/protected double size;
}
如果设置为公开,则不必要地暴露大小
如果设置为protected,装饰者无法通过decoratedCoffee真正访问它(请参阅此帖子Java: cannot access a protected member of the superclass in the extending subclass和Why can't a derived class call protected member function in this code?)
我可以把它放在CoffeeDecorator中,但是我必须将构造函数修改为
public CoffeeDecorator(Coffee c) {
if c is of type CoffeeDecorator
size = c.size;
this.decoratedCoffee = c;
}
哪种方式看起来不是最优雅的解决方案......(显然在我找到一个非空的大小之前挖掘decoratedCoffee
的链也不是一种选择。
我可以把它放在每个装饰器中,这违反了设计原则。
我很确定这种情况经常出现,我想知道处理此类案件的最佳方法是什么?
提前致谢。
---编辑31/3/2016 ---
澄清某些属性(以前的杯子尺寸,现在改名为咖啡尺寸)是所有咖啡都应该有的。
答案 0 :(得分:0)
我不认为将杯子大小添加到这些课程中是一个好主意。 它只是不适合那里,因为咖啡对杯子一无所知。
Cup
可以是一个单独的类(作为伪代码的代码,我对java语法不是很熟悉):
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
}
}
现在你可以做new BigCup(new WithMilk(new Coffee()))
。
或者Cup
也可以是一个装饰者,它在编程方面是有意义的,但在现实生活方面可能没什么意义(因为现在杯子也实现了咖啡,听起来很有趣):
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
}
}