Decorator デザイン パターンには、ItemClass (pe Coffee)、Coffee への参照を含む AbstractDecorator (pe CoffeeDecorator)、および ConcreteDecorators (ミルクなど) があります。私の質問は、なぜ AbstractDecorator クラスが必要なのか、なぜ Concrete Decorators が Coffee クラスから直接継承しないのかということです。あるいは、ConcreteDecorators が ItemClass への参照を持つようにしたいのであれば、なぜ ItemClass プロパティを含むインターフェースを持たないのでしょうか? この AbstractDecorator を使用して、ConcreteDecorators が他のクラスを継承するオプションを無効にしているだけです。前もって感謝します!
1 に答える
1
抽象クラスを使用して、具体的なクラスから重複を取り除きます。デコレータ パターンでは、装飾されたオブジェクト インスタンスの格納と呼び出しの受け渡しが重複しています。このロジックをベース (抽象) デコレーターに移動しない場合は、すべての具象デコレーターでこれを実装する必要があります。
次の飲料インターフェイスを検討してください。
public interface IBeverage
{
decimal Price { get; }
string Description { get; }
}
これはコーヒーによって実装されています:
public class Coffee : IBeverage
{
public decimal Price
{
get { return 3.5M; }
}
public string Description
{
get { return "Coffee"; }
}
}
次に、コーヒー用の最初のデコレータを作成します。現時点では抽象デコレータを作成する必要はありません。私たちのミルクビーを無料でどうぞ。必要な最も単純なコードを書くだけです。
public class Milk : IBeverage
{
private readonly IBeverage _beverage;
public Milk(IBeverage beverage)
{
_beverage = beverage;
}
public decimal Price
{
get { return _beverage.Price; } // price not changed
}
public string Description
{
get { return _beverage.Description + " with milk"; }
}
}
ここで、別のデコレータが必要です。クリームにしましょう:
public class Cream : IBeverage
{
private readonly IBeverage _beverage;
public Cream(IBeverage beverage)
{
_beverage = beverage;
}
public decimal Price
{
get { return _beverage.Price + 2M; }
}
public string Description
{
get { return _beverage.Description + " with cream"; }
}
}
重複したコードが表示されます。それでは、リファクタリングの時間です。複製されたコードをベースの抽象デコレータ クラスに移動しましょう。この責任は、装飾された飲料への参照を保持し、呼び出しを渡します。
public abstract class BeverageDecorator : IBeverage
{
private readonly IBeverage _beverage;
public BeverageDecorator(IBeverage beverage)
{
_beverage = beverage;
}
public virtual decimal Price
{
get { return _beverage.Price; }
}
public virtual string Description
{
get { return _beverage.Description; }
}
}
これで、デコレーターによって動作が変更された呼び出しのみをオーバーライドできるようになりました。ミルク デコレータは次のようになります。
public class Milk : BeverageDecorator
{
public Milk(IBeverage beverage)
: base(beverage)
{
}
public override string Description
{
get
{
return base.Description + " with milk";
}
}
}
ずっときれいですよね?そのため、base デコレーターを使用します。
于 2013-10-18T10:09:06.787 に答える