At the end of his example he uses the next static class diagram
Summarized: the Car is abstract class which is inherited by Toyota and Honda child specialized car classes and a Decorator abstract child class. Decorator class contains a field member of a Car type, which value is been injected through dependency injection (constructor type) and then use implementation over delegation to delegate its implementation of Car abstract methods to the injected instance stored in decorator field
There is no problem as long as inheritance relationship between the Decorator and Car is acceptable. But if we would like to inherit Decorator from some class different then the Car or we wouldn't like to decorate complete car we would have to do some variations in the decorator GoF implementation.
Generic decorator is based upon the inheritance implementation through the usage of Generics.
We would modify Decorator class to become an generic one and remove the inheritance from the Car class so it would look like this:
The modification on Decorator child/specialized classes would look like
Notice that with generics we don't need any more to implement constructor based dependency injection of an Car instance
So the usage of the new decorated class would look like
Summarized: Courtesy of generics we can get the benefits of the decorator patterns without having inheritance limitations . Our taxi car is decorating the car without inheriting from it.
Interface based Decorator
That GoF implementation can be slightly altered in case the base class implements some interface and we would like to decorate just behavior contracted with that interface but not the whole class. One more reason why we would like to do that is maybe because of the need that we would like our Decorator class to inherit from some class other then car, so the base decorator class could be enriched with the certain car attributes. This is the way to get the effect of multiple inheritance in C# I described in my implementation over delegation post.
If we slightly alter the solution Armen explained by introducing the ICar interface , we would se that the solution he has would compile without the single line of code changed (outside of interface definition and defining its implementation by Decorator and Car classes).
So, the decouple decorator taking whole functionality of the base class case could look like this
Another example of the same idea of interface based decorator is that car would implement (beside ICar) an IParkable interface with the AutoPark method. In implementing the TaxiCar I would like to "steal" the IParkable behavior of the car and decorate my taxi with it without "decorating" the behavior defined with the ICar.
Something like this.
Decorator is very powerful pattern which can be used for supplementing the inheritance relationship with composition based relationship. The basic idea stated in GoF is very flexible and it can be implemented on several different ways
I presented here how it can be done through Interfaces and Generics, but I'm sure there are some other ways it can be done more.
Quote of the day:
If the facts don't fit the theory, change the facts. - Albert Einstein
|Share this post :|