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

时间:2013-04-18 19:36:17

标签: c# decorator

这个线程Decorator pattern implementation有一个使用抽象类的装饰器的实现。我不喜欢它的简单事实,即CondimentDecorator不是那里给出的实施中的饮料。我会使用接口代替。对于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

1 个答案:

答案 0 :(得分:4)

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

现在,当您实现任何模式时,通常会有足够的信息来查看是否需要数据字段。但是,随着软件的发展,您几乎无法排除未来需要在其他模式中使用相同的类。从这个角度来看,接口对抽象类的一般偏好为您提供了更长期的灵活性 - 只要您有选择。

根据装饰者的性质,你可以选择。组件通常没有预定义的嵌套方式。如果他们这样做,你将直接使用继承,而不是组件。所以你应该更喜欢使用接口来组成一个装饰器。

所有这一切,你的原始论点也是有效的。装饰器组件(功能)可以理解为 - 如果你喜欢的话,就是一种关系;但这并不是看待它们最自然的方式。