我在學習裝飾設計模式。在這個例子中,我創建了一個應用程序,根據咖啡的類型(意式濃縮咖啡,咖啡豆,混合咖啡),大小(高,大,通風)和調味品裝飾(大豆,奶油,蒸牛奶) - 爲簡潔起見,排除一些代碼。從底部的輸出中可以看到,如果setSize(GRANDE)並且不包裝對象,getSize()將返回GRANDE。如果我設置大小(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按照此()它打印「高」作爲下一行的大小:
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衆議院混合咖啡$ 0.89
-----------------------
GRANDE衆議院混合咖啡$ 0.89
高層住宅混合咖啡,大豆$ 1.04
- ---------------------
GRANDE衆議院混合咖啡$ 0.89
GRANDE衆議院混合咖啡,大豆$ 1.04
此外,你可能會考慮重構你的類。目前,裝飾器正在繼承不必要的基類成員。我會在只有抽象方法(足夠描述你的(裝飾)對象的公共API)的基礎類的基礎上提出一個改變。然後創建一個抽象類來實現這些方法,這些方法有私有或受保護的成員。像HouseBlend這樣的特定實現可以擴展這個類。 – DevCybran
創建另一個抽象類('BeverageDecorator'),該類實現只有一個成員的基類方法 - 「Beverage」的一個實例。所有方法都應該將調用委託給此成員。裝飾者,比如'Soy',可以擴展這個類並且只覆蓋必要的方法。 – DevCybran