Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Decorators - Interfaces or Abstract Classes?

Tags:

c#

decorator

This thread, Decorator pattern implementation, has an implementation of a decorator using abstract classes. I don't like it for the simple fact that a CondimentDecorator is NOT a Beverage in the implementation given there. I'd use interfaces instead. Aren't abstract classes better for is-a relationships, and interfaces better for has-a relationships?

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
like image 279
Scott Avatar asked Apr 18 '13 19:04

Scott


1 Answers

Both base clases and interfaces are frequently used to model is-a relationships. Even an interface as simple as IDisposable can be understood as "is an object with a manually controlled lifecycle", a "disposable". The more tangible differences are in whether base implementation or data fields are allowed; and in their ability to combine multiple hierarchies.

Now, when you are implementing any pattern, you usually have enough information to see whether you need data fields or not. However, you will hardly ever be able to rule out a future need to involve the same classes in additional patterns as your software grows. From that perspective, a general preference of interfaces over abstract classes gives you more long term flexibility - whenever you have a choice.

By the nature of a Decorator, you have a choice. The components typically do not have a predefined order of how they should nest. If they did, you would use inheritance directly, instead of components. So you should prefer interfaces to compose a Decorator.

All that said, your original argument is valid as well. Decorator components (features) can be understood as is-a relationships if you like; but it is not the most natural way of looking at them.

like image 105
Jirka Hanika Avatar answered Oct 10 '22 06:10

Jirka Hanika