14

という名前のクラスがありA、decorator デザイン パターンを使用したいとします。間違っている場合は訂正してください。ただし、それを機能させるADecoratorには、インスタンスへの参照を保持するデコレータ クラス (たとえば、 )を作成する必要がありAます。他のすべてのデコレータはこれを拡張して機能を追加します。

Aインスタンスを使用する代わりに、デコレータ クラスを作成する必要がある理由がわかりません。

4

3 に答える 3

26

デコレーター パターンは、動的に (つまり、実行時に) オブジェクトに機能を追加するために使用されます。通常、クラスを作成すると、オブジェクトの機能が固定されます。ただし、重要な点は、オブジェクトの機能が、オブジェクトのクライアントに対して透過的な方法で拡張されることです。これは、元のオブジェクトが装飾されたオブジェクトに責任を委任するのと同じインターフェイスを実装するためです。

デコレータ パターンは、オブジェクトに多くのオプション機能があるシナリオで機能します。デコレータ パターンがないと、オブジェクト オプションの構成ごとに異なるクラスを作成する必要があります。非常に便利な例の 1 つは、O'Reilly のHead First Design Patternsブックからのものです。スターバックスのように聞こえるコーヒー ショップの例を使用しています。

したがって、コストのような方法で基本的なコーヒーができます。

public double cost(){
     return 3.45;
}

次に、顧客は 0.35 のコストでクリームを追加できるので、コスト メソッドを使用して CoffeeCream クラスを作成します。

public double cost(){
    return 3.80;
}

次に、顧客は 0.5 のモカを希望し、クリーム付きのモカまたはクリームなしのモカを希望する場合があります。そこで、クラス CoffeeMochaCream と CoffeeMocha を作成します。次に、顧客がダブルクリームを欲しがるので、CoffeeCreamCream などのクラスを作成します。最終的にクラス爆発が発生します。使用された悪い例を許してください。少し遅れており、些細なことだとはわかっていますが、要点を表現しています。

代わりに、抽象コスト メソッドを使用して Item 抽象クラスを作成できます。

public abstract class Item{
    public abstract double cost();
}

また、Item を拡張する具体的な Coffee クラスを作成できます。

public class Coffee extends Item{
    public double cost(){
       return 3.45;
    }
}

次に、同じインターフェースを拡張し、Item を含む CoffeeDecorator を作成します。

public abstract class CoffeeDecorator extends Item{
     private Item item;
     ...
}

次に、オプションごとに具体的なデコレータを作成できます。

public class Mocha extends CoffeeDecorator{

   public double cost(){
     return item.cost() + 0.5;
   }

}

Item である限り、デコレータはラップするオブジェクトのタイプを気にしないことに注意してください。item オブジェクトの cost() を使用し、単純に独自のコストを追加します。

public class Cream extends CoffeeDecorator{

   public double cost(){
     return item.cost() + 0.35;
   }

}

これらの少数のクラスで多数の構成が可能になりました。

 Item drink = new Cream(new Mocha(new Coffee))); //Mocha with cream

また

 Item drink = new Cream(new Mocha(new Cream(new Coffee))));//Mocha with double cream

等々。

于 2008-11-08T02:21:46.350 に答える
3

ところで、パターンを始めたばかりなら、Head First Design Patterns の本は驚異的です。概念を簡単に理解できるようにし、同様のパターンを非常に理解しやすい方法で対比して比較します。

于 2008-11-08T05:09:06.823 に答える
2

一部の言語 (Ruby や JavaScript など) では、A インスタンスに新しい機能を追加するだけで済みます。あなたの質問には Java のタグが付けられていることに気付きました。Java でこれを行うことができない理由を尋ねていると思います。その理由は、Java が静的に型付けされているためです。A インスタンスは、クラス A が定義または継承するメソッドのみを持つことができます。したがって、実行時に A が定義していないメソッドを A インスタンスに与える場合は、この新しいメソッドを別のクラスで定義する必要があります。

于 2008-11-08T00:04:10.450 に答える