我正在尝试学习装饰器设计模式。在这个例子中,我创建了一个应用程序,它根据咖啡的类型(浓缩咖啡、无咖啡因、混合咖啡)、大小(高、大、文蒂)和调味品(大 bean 、生奶油、蒸牛奶)计算咖啡的成本-- 为简洁起见,排除了一些代码。
从底部的输出中可以看出,如果我 setSize(GRANDE) 并且不包装对象,则 getSize() 返回 GRANDE。
如果我 setSize(GRANDE),然后装饰对象,getSize() 返回 TALL(在 Beverage 类中设置的默认值)。
如果我 setSize(GRANDE),装饰对象,再次 setSize(GRANDE),然后 getSize() 返回 GRANDE。
注意:虽然尺寸打印不正确,但成本计算正确。
问题: 有没有办法对此进行编码,因此当我 setSize() 时,即使在对象被装饰之后,它也会保持该值?
package coffee;
public abstract class Beverage {
String description = "Unknown Beverage";
public enum Size { TALL, GRANDE, VENTI };
Size size = Size.TALL;
public String getDescription() {
return description;
}
public void setSize(Size size) {
this.size = size;
}
public Size getSize() {
return size;
}
public abstract double cost();
}
package coffee;
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
package coffee;
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
public double cost(){
return .89;
}
}
package coffee;
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
double cost = beverage.cost();
if( beverage.getSize() == Size.TALL) {
cost += .10;
} else if( beverage.getSize() == Size.GRANDE) {
cost += .15;
}else if( beverage.getSize() == Size.VENTI) {
cost += .20;
}
return cost;
}
}
package coffee;
import coffee.Beverage.Size;
public class StarbuzzCoffeeController {
public static void main(String[] args) {
Beverage beverage = new HouseBlend();
System.out.println( beverage.getSize() + " " + beverage.getDescription() + " $" + String.format("%.2f", beverage.cost() ));
beverage.setSize(Size.GRANDE);
System.out.println( beverage.getSize() + " " + beverage.getDescription() + " $" + String.format("%.2f", beverage.cost() ));
System.out.println("-----------------------");
Beverage beverage2 = new HouseBlend();
beverage2.setSize(Size.GRANDE);
System.out.println( beverage2.getSize() + " " + beverage2.getDescription() + " $" + String.format("%.2f", beverage2.cost() ));
如果我不使用另一个 setSize() 跟随它,它会在下一行打印“TALL”作为大小:
beverage2 = new Soy(beverage2);
System.out.println( beverage2.getSize() + " " + beverage2.getDescription() + " $" + String.format("%.2f", beverage2.cost() ));
System.out.println("-----------------------");
Beverage beverage3 = new HouseBlend();
beverage3.setSize(Size.GRANDE);
System.out.println( beverage3.getSize() + " " + beverage3.getDescription() + " $" + String.format("%.2f", beverage3.cost() ));
beverage3 = new Soy(beverage3);
如果我在装饰对象后再次 setSize() ,则大小将正确打印为 GRANDE:
beverage3.setSize(Size.GRANDE);
System.out.println( beverage3.getSize() + " " + beverage3.getDescription() + " $" + String.format("%.2f", beverage3.cost() ));
}
}
输出::
高屋混合咖啡 $0.89
GRANDE House 混合咖啡 $0.89
-----------------------
GRANDE House 混合咖啡 $0.89
TALL House Blend 咖啡,大 bean 1.04 美元
-----------------------
GRANDE House 混合咖啡 $0.89
GRANDE House 混合咖啡,大 bean 1.04 美元
最佳答案
您的类 Soy
不会覆盖 getSize()
方法 - 因此,使用基类的默认实现。并且基类返回它自己的 size
成员,该成员被初始化为 TALL。
为了解决这个问题,你必须在你的类 getSize()
中相应地覆盖 Soy
方法:
@Override
public Size getSize() {
return this.beverage.getSize();
}
这将正确返回装饰对象的大小。
关于java - 装饰对象时变量重置为默认值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34047373/