2017-12-02 5 views
1

私は本 "ヘッドファーストデザインパターン"のデコレータパターンの例で遊んでいます。私はbeverage3のフィールド記述の値は "ハウスブレンドコーヒー"でなければならないと思ったが、それは "不明な飲み物"である。デコレータパターン:コンクリートコンポーネントのフィールドの値はコンポーネントからのフィールドの値ですが、なぜですか?

誰かがこれを説明できますか?私たちはインタフェースに対してコード化していますが(この例では抽象クラスです)、HouseBlendクラスをインスタンス化しているので、値は "House Blend Coffee"にする必要がありますが、そうではありません。

以下のコードは、この例のすべてのクラスを含んでいません。

public class StarbuzzCoffee { 

public static void main(String[] args) { 
    Beverage beverage = new Espresso(); 
    System.out.println(beverage.getDescription() 
      + " $" + beverage.cost()); 

    Beverage beverage2 = new DarkRoast(); 
    beverage2 = new Mocha(beverage2); 
    beverage2 = new Mocha(beverage2); 
    beverage2 = new Whip(beverage2); 
    System.out.println(beverage2.getDescription() 
      + " $" + beverage2.cost()); 

    Beverage beverage3 = new HouseBlend(); 
    System.out.println("(added by me)return value of getDescription() without condiment: " + beverage3.getDescription()); 
    beverage3 = new Soy(beverage3); 
    beverage3 = new Mocha(beverage3); 
    beverage3 = new Whip(beverage3); 
    System.out.println(beverage3.getDescription() 
      + " $" + beverage3.cost()); 

    System.out.println("(added by me)value of field desciption: " + beverage3.description); 
    } 
} 

Beverage.java

public abstract class Beverage { 

    String description = "Unknown Beverage"; 

    public String getDescription() { 
     return description; 
    } 

    public abstract double cost(); 
} 

CondimentDecorator.java

public abstract class CondimentDecorator extends Beverage { 

    public abstract String getDescription(); 
} 

HouseBlend.java

public class HouseBlend extends Beverage{ 

    public HouseBlend() { 
     description = "House Blend Coffee"; 
    } 
    @Override 
    public double cost() { 
     return .89; 
    } 

} 

CondimentDecorator.java

public class Mocha extends CondimentDecorator{ 

    Beverage beverage; 

    public Mocha(Beverage beverage) { 
     this.beverage = beverage; 
    } 

    @Override 
    public String getDescription() { 
     return beverage.getDescription() + ", Mocha"; 
    } 

    @Override 
    public double cost() { 
     return beverage.cost() + .20; 
    } 

} 
+0

私はあなたに役立つ答えを追加しました。あなたはまだ疑問があるならば、ただ聞いてください。私は前にこの問題に噛まれてきた...乾杯! – wleao

答えて

1

問題は、作成しているモカオブジェクト自体が説明を持つ飲み物であることです。あなたはその記述を変更していませんでした。あなたは別の飲み物を渡して、装飾されたオブジェクトの説明を強調しています。しかし、あなたはまだMochaオブジェクトのあなたの以前の記述をそこに持っています。その説明を直接アクセスすると(getDescriptionメソッドを使用しないことで行ったことです)、未変更のフィールドにアクセスしているので、「Unknown Beverage」が表示されます。

作成するすべての飲み物には、フィールドの説明が付きます。あなたがそれを変更することなくそれを使用する場合、あなたは "不明な飲み物"を取得します。

BeverageクラスのString記述をprotectedにし、Beverageの実装のオーバーライドされたgetDescriptionメソッドを介してのみアクセスします。それをチェックアウト:

デザインについて
public class StarbuzzCoffee { 

    public static void main(String[] args) { 
     Beverage beverage3 = new HouseBlend(); 
     System.out 
      .println("(added by me)return value of getDescription() without condiment: " + beverage3.getDescription()); 
     beverage3 = new Mocha(beverage3); 
     System.out.println(beverage3.getDescription() + " $" + beverage3.cost()); 

     System.out.println("(added by me)value of field desciption: " + beverage3.getDescription()); 
    } 
} 

abstract class Beverage { 

    protected String description = "Unknown Beverage"; 

    public String getDescription() { 
     return description; 
    } 

    public abstract double cost(); 
} 

abstract class CondimentDecorator extends Beverage { 

    public abstract String getDescription(); 
} 

class HouseBlend extends Beverage{ 

    public HouseBlend() { 
    description = "House Blend Coffee"; 
    } 
    @Override 
    public double cost() { 
     return .89; 
    } 

} 

class Mocha extends CondimentDecorator{ 

    Beverage beverage; 

    public Mocha(Beverage beverage) { 
     this.beverage = beverage; 
    } 

    @Override 
    public String getDescription() { 
     return beverage.getDescription() + ", Mocha"; 
    } 

    @Override 
    public double cost() { 
     return beverage.cost() + .20; 
    } 

} 

、飲料ののgetDescriptionは、抽象的にし、それを上書きする全ての実施を強制する方が安全だろう。そうすれば、将来このような問題を避けることができます。それをチェックアウト:

public class StarbuzzCoffee { 

    public static void main(String[] args) { 
     Beverage beverage3 = new HouseBlend(); 
     System.out 
      .println("(added by me)return value of getDescription() without condiment: " + beverage3.getDescription()); 
     beverage3 = new Mocha(beverage3); 
     System.out.println(beverage3.getDescription() + " $" + beverage3.cost()); 

     System.out.println("(added by me)value of field desciption: " + beverage3.description); 
    } 

} 

abstract class Beverage { 

    protected String description = "Unknown Beverage"; 

    public abstract String getDescription(); 

    public abstract double cost(); 
} 

abstract class CondimentDecorator extends Beverage { 
    // You don't need this code here. Because Beverage already 
    // provides a getDescription 
    // public abstract String getDescription(); 
} 

class HouseBlend extends Beverage{ 

    public HouseBlend() { 
    description = "House Blend Coffee"; 
    } 

    @Override 
    public String getDescription() { 
    return description; 
    } 

    @Override 
    public double cost() { 
     return .89; 
    } 

} 

class Mocha extends CondimentDecorator{ 
    // Also make sure that this guy here is private 
    // so other objects can't change or access 
    // its state without going through Mocha 
    private Beverage beverage; 

    public Mocha(Beverage beverage) { 
     this.beverage = beverage; 
    } 

    @Override 
    public String getDescription() { 
     return beverage.getDescription() + ", Mocha"; 
    } 

    @Override 
    public double cost() { 
     return beverage.cost() + .20; 
    } 

} 
関連する問題