実際にはいくつかの問題があります (おそらく Java とは異なる設計)。命名の問題をすべて整理した後でも、期待どおりの結果が得られません。
public abstract class CondimentDecorator : IBeverage {
public abstract string GetDescription();
}
CondimentDecorator
クラスは実際には version メソッドを非表示にしますIBeverage
(GetDescription()
技術的にはpublic new abstract string GetDescription();
.
クラスを変数に割り当てることでMocha
クラスを として分類しています (以前に を介して IBeverage として定義しました 。メソッドのバージョンが実際に起動するものです (メソッドのオーバーライドを完全に無視します) 。IBeverage
b
IBeverage b = new Espresso()
IBeverage
GetDescription()
Mocha
CondimentDecorator
GetDescription()
コードをステップ実行すると、これを確認できます。使ってみて
CondimentDecorator m = new Mocha(b);
Console.WriteLine(m.GetDescription());
そしてあなたはあなたが期待するものを手に入れるでしょう。
ただし、私の意見では、この種のデコレータを使用する目的は無効です。より良いオプションは、デザインを少し変更して CondimentDecorator を取り除くことです。混乱と予期しない動作以外は何も提供していません。代わりにこれを試してください:
これは、必要な唯一の抽象 Beverage クラスです。
public abstract class Beverage
{
// c# convention is to use properties instead of public fields.
// In this case I've used a private readonly backing field.
private readonly string _description = "Unknown Beverage";
protected string Description
{
get { return _description; }
set { _description = value; }
}
// Make this method virtual so you can override it, but if you
// choose not to, this is the default behaviour.
public virtual string GetDescription()
{
return Description;
}
}
これは標準的な飲料クラスです (装飾可能):
public class Espresso : Beverage
{
public Espresso()
{
// Setting the Beverage class Description property.
// You can use base.Description if you prefer to be explicit
Description = "Espresso";
}
}
これは、別の Beverage クラスをデコレートする Beverage クラスです。
public class Mocha : Beverage
{
// store an instance of the Beverage class to be decorated
private readonly Beverage _beverage;
// Beverage instance to be decorated is passed in via constructor
public Mocha(Beverage beverage)
{
_beverage = beverage;
}
// Override Beverage.GetDescription
public override string GetDescription()
{
// Calls decorated Beverage's GetDescription and appends to it.
return _beverage.GetDescription() + ", Mocha";
}
}
そして、期待どおりの動作を得るために、上記と同じコードを実行できます。
static void Main(string[] args)
{
Beverage b = new Espresso();
Console.WriteLine(b.getDescription()); // "Espresso"
b = new Mocha(b);
Console.WriteLine(b.getDescription()); // "Espresso, Mocha"
Console.ReadKey();
}
補足として。 +を使用Console.ReadKey();
すると、デバッグ時に 使用を避けることができます。これは自動的に挿入されます。CtrlF5 "Press any key to continue..."
アップデート
CondimentDecorator クラスを含めたいので (コメントで述べたように)、次のクラスを作成できます。
public abstract class CondimentDecorator : Beverage
{
private readonly Beverage _beverage;
protected Beverage Bevy
{
get { return _beverage; }
}
protected CondimentDecorator(Beverage beverage)
{
_beverage = beverage;
}
}
次に、Mocha
クラスを次のように変更します。
// override CondimentDecorator instead of Beverage
public class Mocha : CondimentDecorator
{
// Pass the Beverage to be decorated to the base constructor
// (CondimentDecorator)
public Mocha(Beverage beverage)
: base(beverage)
{
// nothing needed in this constructor
}
public override string GetDescription()
{
// Now access the CondimentDecorator's Beverage property
// (which I called Bevy to differentiate it)
return Bevy.GetDescription() + ", Mocha";
}
}