2016-03-30 10 views
2

古典的なコーヒーデコレータの例(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; 
    } 
} 

のは、すべてのデコレータ(例えばミルク)の価格は、すべてのコーヒーを持っている(コーヒーの大きさを言う)、コーヒーの大きさは他の場所では使用されないことになると、いくつかの属性に依存して、今言ってみましょう。どこのクラスの階層にコーヒーのサイズを追加する必要がありますか?

私は(それが公衆に設定すると、それが保護に設定すると、サイズが不必要

を暴露され、デコレータは本当にdecoratedCoffeeを介してアクセスすることはできませんコーヒーインタフェース

public interface Coffee { 
    public double getCost(); // Returns the cost of the coffee 
    public/protected double size; 
} 

にそれを置くことができます私はCoffeeDecoratorにそれを置くことができます

この記事Java: cannot access a protected member of the superclass in the extending subclassWhy can't a derived class call protected member function in this code?)を参照してください、その後私は

にコンストラクタを変更する必要があります私は置くことができます(私はnull以外のサイズのいずれかがどちらかのオプションではありません見つけるまで明らかに decoratedCoffee秒のチェーンを掘り)何とか...最もエレガントな解決策のように見えるしていません
public CoffeeDecorator(Coffee c) { 
    if c is of type CoffeeDecorator 
     size = c.size; 
    this.decoratedCoffee = c; 
} 

それは単にデザイン原則に反する各デコレータにあります。

私はこのシナリオがかなり頻繁に起こると確信しています。そのようなケースを処理する最良の方法は何か知りたいのですが?

ありがとうございます。

---編集31/3/2016 ---

特定の属性(今コーヒーサイズに改名以前カップサイズは、)すべてのコーヒーを持っているべきものであることを明確にします。

答えて

0

カップのサイズをこれらのクラスに追加することはお勧めできません。 コーヒーはカップについて何も知らないので、ちょうどそこには収まりません。

Cupは別のクラスすることができます(擬似コードとしてtheatコード、私は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 
    } 

} 
+0

おそらく、コーヒーサイズはより良い用語になるだろう、キーはデコレータがすべてのコーヒーに存在する「いくつかの属性」に依存していることである、私は明確にするだろう – Woofas

+0

@Woofasそれでも明確ではない、 "コーヒーサイズ"はどういう意味ですか?そしてデコレータがそれにどれだけ依存しているのですか?なぜ、getCost()(いくつかの 'getSize()'メソッド)と同じ方法で追加することはできませんか、この属性をまったく公開せず、tell([tell、do not ask] http://martinfowler.com/bliki/TellDontAsk.html)) 'コーヒー'オブジェクトは、この 'サイズ'に応じて何かをするのですか?一般的に、 'coffee size'の例はまだ現実的ではないので、正確に何が問題なのか明確ではありません。 –

関連する問題