您实际上在这里遇到了一些问题(可能与 Java 的设计不同)。即使在对所有命名问题进行排序之后,您也不会得到您期望的结果。
public abstract class CondimentDecorator : IBeverage {
public abstract string GetDescription();
}
该类CondimentDecorator
实际上将隐藏IBeverage
版本GetDescription()
方法(从技术上讲,您应该使用public new abstract string GetDescription();
.
您通过将Mocha
类IBeverage
分配给b
变量(您之前将其定义为 IBeverage via 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();
您可以在调试时 避免使用Ctrl+F5 这将自动"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";
}
}