2017-01-26 6 views
2

を取り外し、GoFのがはっきりと述べている:デコレーターでDecoratorパターンは:デコデザインパターンについては責任

を、責任は、単にそれらを着脱することにより、実行時 で追加および削除することができます。

私はこのパターンがデコレートされていないオブジェクトにどのように責任を加えることができるのかを簡単に見ることができるC++でスケルトンコードを作成しようとしています。

私の質問は、どのように特定の責任を取り除くことができますか?最後にラップされた責任の削除は簡単に行うことができます。しかし、間に追加された責任を取り除くこともできますか?ここで

は私のサンプルコードです:

class Icecream { //Component 
    public : 
    virtual void addToppings() = 0 ; 
    virtual Icecream *getUndecorated() = 0 ; 
} ; 
class PlainIcecream : public Icecream { //Concrete Component 
    public : 
    void addToppings() { cout<<"I am just plain icecream, you may add more flavors\n" ; } 
    Icecream * getUndecorated() {return this ; } 
} ; 
class Topping : public Icecream { //Decorator 
    protected : 
    Icecream *icecream ; 
    public : 
    Topping(Icecream *i) : icecream(i) {} 
    void addToppings() { icecream->addToppings() ; } 
} ; 
class PeanutToppings : public Topping { //Concrete Component A 
    public : 
    PeanutToppings(Icecream *i) : Topping(i) {} 
    void addToppings() { 
     Topping::addToppings() ; 
     cout<<"Adding peanut toppings for great taste\n" ; 
    } 
    Icecream * getUndecorated() {return icecream ; } 
} ; 
class CandyToppings : public Topping { //Concrete Component A 
    public : 
    CandyToppings(Icecream *i) : Topping(i) {} 
    void addToppings() { 
     Topping::addToppings() ; 
     cout<<"Adding candy toppings for yummy flavour\n" ; 
    } 
    Icecream * getUndecorated() {return icecream ; } 
} ; 
main() { 
    Icecream *icecream_with_candy_and_peanuts = new CandyToppings(new PeanutToppings(new PlainIcecream)) ; 
    icecream_with_candy_and_peanuts->addToppings() ; 
    cout<<"_________________________________________________\n" ; 
    Icecream *icecream_with_only_peanuts = icecream_with_candy_and_peanuts->getUndecorated() ; 
    icecream_with_only_peanuts->addToppings() ; 
    cout<<"_________________________________________________\n" ; 
    Icecream *icecream_plain = icecream_with_only_peanuts->getUndecorated() ; 
    icecream_plain->addToppings() ; 
} 

今、私はicecream_with_candy_and_peanutsからトッピングだけお菓子とアイスクリームを持っていることが可能であるかどうかを知りたいです。なぜ私はそうしたいのではないか考えてください。私はちょうどGoFの中で述べたように

が責任

を取り外す用語を理解しようとしています。

最後のラップの責任を削除
+3

トッピングは本当にアイスクリームではないので、デザインに欠陥があるようです。継承は「関係」であることを忘れないでください。 –

+0

@プログラマの中には、基本クラス、派生クラスと考えることができます。私はすでに、クラス名ではなく、GoFで述べたように、装飾オブジェクトからの責任を取り除くことが懸念されていることをすでに述べました。あなたはこれらのクラスに名前をつけたいと思っています。 – user3282758

+0

@プログラマの人は、あなたが考えてほしいスケルトンであり、クラス名はまったく意味がありません。 – user3282758

答えて

1

は簡単

別々getUndecoratedメソッドを持ってする必要はありません行うことができます。これは標準の一部ではありませんデコレータパターン定義。

今、私ははいすることができますicecream_with_candy_and_peanuts

からトッピングだけお菓子とアイスクリームを持つことが可能であるかどうかを知りたいです。デコレータパターンになると、が付くまたはがデタッチの間に大きな違いはありません。 デタッチ責任にするには、もう一度、あなたのコンポーネントを再作成する必要があります:私は両方のケースで*icecreamを使用していますか

//attaching responsibilities 
Icecream *icecream = new new PlainIcecream(); 
*icecream = new PeanutToppings(icecream);//wrap around with new respnsibility 
*icecream = new CandyToppings(icecream);//wrap around with new responsiblity 

//detaching responsibilities 
*icecream = new CandyToppings(new PlainIcecream()); 

お知らせ。 には、デタッチの責任を1つのインタフェース(つまり、IceCream)に限定することができます。それはデコレータパターンの背後にあるアイデアです。言っ

、使用して実装コンポジットパターンHashMap(キーはトッピング名前です)あなたは、任意の既存のインスタンスから責任を追加または削除できるようにしたいシナリオでは、より良い選択です。

ボーナスのヒントデコレータのデコレータパターンは、理想的にはインスタンス化できません(あなたの場合はToppings)。代わりにToppingsからToppingsDecoratorに名前を変更することもできます。これは純粋に他の読者の利益のためです)

+0

あなたの答えがよく書かれています。しかし、私はまだクエリを持っています。つまり、新しいインスタンスを作成し、この新しいインスタンスを同じポインタで参照しています。これは、icecreamポインタで参照される元のオブジェクトは、責任を減らすことができないことを意味します。 – user3282758

+0

@ user3282758デコレータパターンの背後にある考え方は、責任を持ってオブジェクトを折り返すことです。 * wrapping *を行うには、古いインスタンスの周りに新しい責任をラップする新しいインスタンスを作成する必要があります(あなたが*添付するかどうかは関係ありません)。あなたは*責任を1ステップで結びつけます。オリジナルの '* icecream * 'に私が* attach *と* detach *の責任を負わせる私の編集を見てください。私の答えは構文的に正しくないかもしれないので、私のC++は錆びていることに注意してください。エラーを修正してエラーを削除してください。 – CKing

+0

私はあなたの意見を受け取ります – user3282758

関連する問題