我看到了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());
所以,我不需要记住东西的顺序。 而且,我认为这里的所有东西都是装饰者(这是个坏主意吗?) 这些实施的缺点是什么?
答案 0 :(得分:1)
这对我来说看起来很合理,但是通过添加用作默认委托对象的具体Null Object可以略微改进,从而避免空检查。
以我的语言语法为基础(这是我实际上并不使用的语言),这看起来像这样:
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();
}
}