加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c#-4.0 – 尝试装饰器设计模式,这段代码出了什么问题?

发布时间:2020-12-16 01:54:35 所属栏目:百科 来源:网络整理
导读:我有这个代码解释装饰模式: public abstract class IBeverage { protected string description = "Unknown beverage"; public virtual string getDescription() { return description; }}public abstract class CondimentDecorator : IBeverage { public ab
我有这个代码解释装饰模式:

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();.
>您将Mocha类分类为IBeverage,方法是将其分配给b变量(您之前通过IBeverage b = new Espresso()定义为IBeverage,Getecription()方法的IBeverage版本实际上是触发的(完全忽略)调用CondimentDecorator的Mocha覆盖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";
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读