Reputation: 53
In Decorator pattern, an abstract class implements an interface and a concrete class (Decorator) extends the abstract class. What happens to the functionality of the pattern if the concrete class directly implements the interface instead of inheriting it through an abstract class?
Upvotes: 1
Views: 131
Reputation: 233150
The original Design Patterns book (GoF) is from 1994 and uses C++ and SmallTalk for examples. IIRC, C++ doesn't have language-level interfaces (at least not in 1994). When the book admonishes
Program to an interface, not an implementation
you should interpret the word interface as a concept rather than a language construct.
In C++, for example, it's common to emulate interfaces with abstract classes that exclusively define pure virtual functions. Many of the C++ examples in the GoF book do this.
There's a strong relationship between abstract classes and interfaces, to the point where they're de-facto interchangeable.
As to the Decorator pattern, I conjecture that it's always possible to decorate an interface. Consider, for example, an interface like this:
public interface IFace
{
void Command(Arg1 arg1, Arg2 arg2);
Ret1 Query(Arg3);
}
AFAICT, you can always write a Decorator of IFace
- at the very least a degenerate Decorator:
public class MyFace : IFace
{
private readonly IFace inner;
public MyFace(IFace inner)
{
this.inner = inner;
}
public void Command(Arg1 arg1, Arg2 arg2)
{
// Consider doing something interesting here...
inner.Command(arg1, arg2);
// ... or here
}
public Ret1 Query(Arg3)
{
// Consider doing something interesting here...
Ret1 ret = inner.Query(arg3);
// ... or here
return ret;
}
}
Thus, it makes no difference to the Decorator pattern whether you use an abstract class or an interface.
Upvotes: 1
Reputation: 17066
The abstract class is not required. From page 179 of the GoF book,
There's no need to define an abstract Decorator class when you only need to add one responsibility. That's often the case when you're dealing with an existing class hierarchy rather than designing a new one. In that case, you can merge Decorator's responsibility for forwarding requests to the component into the ConcreteDecorator.
A similar question from Head First Design is, What is the reason for moving the instance variable into an abstract class in the decorator pattern?
Upvotes: 2