C#装饰器-接口还是抽象类?

C#装饰器-接口还是抽象类?,c#,decorator,C#,Decorator,这个线程有一个使用抽象类的装饰器实现。我不喜欢这个简单的事实,即调味品装饰师在这里给出的实现中不是饮料。我会使用接口。抽象类对于is-a关系不是更好,接口对于has-a关系不是更好吗 public interface IBeverage { // get a description of the beverage String Description { get; } // calculate cost of the beverage double Cost {

这个线程有一个使用抽象类的装饰器实现。我不喜欢这个简单的事实,即调味品装饰师在这里给出的实现中不是饮料。我会使用接口。抽象类对于is-a关系不是更好,接口对于has-a关系不是更好吗

public interface IBeverage
{
    // get a description of the beverage
    String Description { get; }

    // calculate cost of the beverage
    double Cost { get; }
}

// HouseBlend coffee implements IBeverage
public class HouseBlend : IBeverage
{
    private string description;
    public String Description
    {
        get { return description; }
    }

    private double cost;
    public double Cost
    {
        get { return cost; }
    }

    // Constructor
    public HouseBlend() { description = "House Blend"; cost = 0.89;  }
}

// DarkRoast coffee implements IBeverage
public class DarkRoast : IBeverage
{
    private string description;
    public String Description
    {
        get { return description; }
    }

    private double cost;
    public double Cost
    {
        get { return cost;  }
    }

    // Constructor
    public DarkRoast() { description = "Dark Roast"; cost = 1.10; }
}

// Mocha is a Decorator
public class Mocha
{
    // Mocha has-a Beverage
    private IBeverage m_beverage;

    private string description;
    public String Description
    {
        get { return description; }
    }

    private public double Cost
    {
        get { return cost; }
    }

    // Constructor binds the object passed to member var
    public Mocha(IBeverage beverage)
    {
        m_beverage = beverage; // not necessary for the purpose of this example
        description = m_beverage.Description + ", Mocha";
        cost = 0.20 + m_beverage.Cost;
    }
}

Use like this:
    Mocha mhb = new Mocha(new HouseBlend()); // house blend with mocha flavor

基类和接口都经常用于为is-a关系建模。即使像
IDisposable
这样简单的界面也可以理解为“是一个具有手动控制生命周期的对象”,一个“一次性的”。更明显的区别在于是否允许基本实现或数据字段;以及它们组合多个层次结构的能力

现在,当您实现任何模式时,您通常有足够的信息来查看是否需要数据字段。然而,随着软件的发展,您很难排除将来需要在其他模式中包含相同的类。从这个角度来看,与抽象类相比,接口的一般偏好为您提供了更长期的灵活性——只要您有选择

作为一个装饰师,你有一个选择。组件通常没有预定义的嵌套顺序。如果有,您将直接使用继承,而不是组件。因此,您应该更喜欢使用接口来组成装饰器


尽管如此,你最初的论点也是有效的。如果您愿意,装饰器组件(特性)可以理解为is-a关系;但这不是最自然的看待方式。

这可能更适合程序员。stackexchange.com我完全同意,但这不是你所指问题的重点。是的,在不是is-a关系的东西上烧掉你唯一的基类是个坏主意。我想当你想把
Mocha
对象传递给想要
IBeverage
的东西时,问题就来了。怎么做?我想你真的需要一个
Mocha
类来实现
IBeverage
,并使用
MochaDecorator
来帮助实现。如果你为描述和成本添加一个MochaDecorator,并在实现IBeverage的Mocha类中使用它,你就不需要在Mocha类中使用描述和成本。但它们必须由IBeverage实现!不行。也许只是“调味品装饰师”这个名字让我困惑。BeverageDecorator怎么样?它给你一种新型饮料,但它仍然是一种饮料。所以摩卡确实会实施IBeverage。但在这种情况下,我根本不需要额外的BeverageDecorator类。摩卡咖啡现在被称为摩卡咖啡机,我已经喝完了。