在Decorator设计模式中,我们有一个ItemClass(p.e. Coffee),然后是一个AbstractDecorator(p.e. CoffeeDecorator),它包含对Coffee和ConcreteDecorators(如milk)的引用。我的问题是,为什么我们需要AbstractDecorator类,为什么Concrete Decorators不直接从Coffee类继承?或者,如果我们已经想要确保ConcreteDecorators具有对ItemClass的引用,为什么我们没有包含ItemClass属性的接口?使用这个AbstractDecorator我们只是禁用了我们的ConcreteDecorators继承其他类的选项。提前谢谢!
答案 0 :(得分:1)
我们使用抽象类来删除具体类的重复。在装饰器模式中,您有重复存储装饰对象实例并将调用传递给它。如果你不将这个逻辑移动到基础(抽象)装饰器,那么你需要在每个具体的装饰器中实现它。
考虑以下饮料界面:
public interface IBeverage
{
decimal Price { get; }
string Description { get; }
}
由咖啡实施:
public class Coffee : IBeverage
{
public decimal Price
{
get { return 3.5M; }
}
public string Description
{
get { return "Coffee"; }
}
}
现在你要为咖啡创建第一个装饰器。此刻你不需要创建抽象装饰器。让我们的奶蜂免费。只需编写您需要的最简单的代码:
public class Milk : IBeverage
{
private readonly IBeverage _beverage;
public Milk(IBeverage beverage)
{
_beverage = beverage;
}
public decimal Price
{
get { return _beverage.Price; } // price not changed
}
public string Description
{
get { return _beverage.Description + " with milk"; }
}
}
现在你需要另一个装饰者。让它成为奶油:
public class Cream : IBeverage
{
private readonly IBeverage _beverage;
public Cream(IBeverage beverage)
{
_beverage = beverage;
}
public decimal Price
{
get { return _beverage.Price + 2M; }
}
public string Description
{
get { return _beverage.Description + " with cream"; }
}
}
您可以看到重复的代码。所以,现在是重构的时候了。让重复的代码移动到基础抽象装饰器类,该装置将负责控制装饰饮料并将调用传递给它:
public abstract class BeverageDecorator : IBeverage
{
private readonly IBeverage _beverage;
public BeverageDecorator(IBeverage beverage)
{
_beverage = beverage;
}
public virtual decimal Price
{
get { return _beverage.Price; }
}
public virtual string Description
{
get { return _beverage.Description; }
}
}
现在,您只能覆盖装饰器更改了哪些行为的调用。牛奶装饰将看起来像:
public class Milk : BeverageDecorator
{
public Milk(IBeverage beverage)
: base(beverage)
{
}
public override string Description
{
get
{
return base.Description + " with milk";
}
}
}
更清洁,是吗?这就是我们使用基础装饰器的原因。