c#-4.0 – 尝试装饰器设计模式,这段代码出了什么问题?
我有这个代码解释装饰模式:
public abstract class IBeverage { protected string description = "Unknown beverage"; public virtual string getDescription() { return description; } } public abstract class CondimentDecorator : IBeverage { public abstract string getDescription(); } public class Espresso : IBeverage { public Espresso() { description = "Espresso"; } } public class Mocha : CondimentDecorator { IBeverage beverage; public Mocha(IBeverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.getDescription() + ",Mocha"; } } 我应该像以下一样使用它: static void Main(string[] args) { IBeverage b = new Espresso(); Console.WriteLine(b.getDescription()); b = new Mocha(b); Console.WriteLine(b.getDescription()); Console.ReadKey(); } 当我创建饮料时(Beverage b = new Espresso();)_description更新为“Espresso”,当我用Mocha(b =新摩卡(b))装饰b时,_description采用原始值“Unknown Beverage”.它应该是“Espresso,Mocha”.怎么了? 这段代码最初是用Java编写的(这本书是用Java编写的),但是我把它翻译成了C#.我猜Java与C#有点不同. 解决方法
你实际上在这里遇到了一些问题(也许是与Java不同的设计).即使在对所有命名问题进行??排序之后,您也无法获得预期的结果.
public abstract class CondimentDecorator : IBeverage { public abstract string GetDescription(); } > CondimentDecorator类实际上会隐藏IBeverage版本的GetDescription()方法(技术上应该使用公共的新抽象字符串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进行调试时,会自动输入“按任意键继续…”. UPDATE 由于您要包含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"; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |