1

我看到了 Decorator DP 示例,但所有这些都暗示,具体对象将位于链的末尾:

IProduct prod2 = new Sugar(new Sugar(new Sugar(new Milk(new DarkRoast()))));
Console.WriteLine("I am {0}, my cost is {1}", prod2.Name(), prod2.Cost());

DarkRoast 是一个具体的对象,其他对象 - 是一个装饰器。所以,我(或客户)需要记住谁在创造链的和的。

所以,默认情况下,我不能这样做:

IProduct prod2 = new Sugar(new DarkRoast(new Sugar(new Milk(new Sugar()))));
Console.WriteLine("I am {0}, my cost is {1}", prod2.Name(), prod2.Cost());

但是,意思(我认为)是一样的:深烤咖啡 + 3 糖 + 1 牛奶。

因此,我将其重新设计为:

public interface IProduct {
    double Cost();
    string Name();
}

public class DarkRoast : IProduct {
    IProduct _product;

    public DarkRoast(IProduct prod = null) { _product = prod; }

    public double Cost() {
        if (_product != null) { return 2.5 + _product.Cost(); }
        else { return 2.5; }
    }

    public string Name() {
        if (_product != null) { return "DarkRoast " + _product.Name(); }
        else { return "DarkRoast "; }
    }
}

public class Milk : IProduct {
    IProduct _product;

    public Milk(IProduct prod = null) { _product = prod; }

    public double Cost() {
        if (_product != null) { return 0.5 + _product.Cost(); }
        else { return 0.5; }
    }

    public string Name() {
        if (_product != null) { return "With milk " + _product.Name(); }
        else { return "With milk "; }
    }
}

public class Sugar : IProduct {
    IProduct _product;

    public Sugar(IProduct prod = null) { _product = prod; }

    public double Cost() {
        if (_product != null) { return 0.2 + _product.Cost(); }
        else { return 0.2; }
    }

    public string Name() {
        if (_product != null) { return "With sugar " + _product.Name(); }
        else { return "With sugar "; }
    }
}

它让我有可能做到

IProduct prod2 = new Sugar(new DarkRoast(new Sugar(new Milk(new Sugar()))));
Console.WriteLine("I am {0}, my cost is {1}", prod2.Name(), prod2.Cost());

所以,我不需要记住东西的顺序。而且,我认为这里的所有东西都是装饰器(这是一个坏主意吗?)这些实现有什么缺点?

4

1 回答 1

1

这在我看来是合理的,但可以通过添加一个用作默认委托对象的具体Null 对象来稍微改进它,从而避免空值检查。

以我对您的语言语法的了解为模(这是一种我实际上并没有使用的语言),这看起来像这样:

public class Empty : IProduct
{

    public double Cost()
    {
        return 0.0;
    }

    public string Name()
    {
        return "";
    }
}


public class Sugar : IProduct
{
    IProduct _product;


    public Sugar(IProduct prod = null) 
    {  
        _product = (prod == null) ? new Empty() : prod;
    }

    public double Cost()
    {
        return 0.2 + _product.Cost();
    }

    public string Name()
    {
        return "With sugar " + _product.Name();
    }
}
于 2012-09-02T14:00:06.777 回答