Using Decorator Design Pattern in Ruby
The intent of decorator design pattern, as described in Design Patterns by the Gang of Four
is to
attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
To extend the functionality of any object, we use subclassing
(read inheritance
) to add that new function to the subclass while keeping the rest of inherited functionalities from its superclass.
But it is kind of impossible to extend a single object this way because this new function will be applied to the whole class. This is where the Decorator Pattern
comes in handy. We can extend the functionality of a single object without affecting any other
instances of the same class.
Essentially with decorator, we are wrapping the existing object with additional functionality.
Let’s imagine a House
class with a rent method that returns 10000
.
Now we need to represent house with more bedrooms, the rent goes up by 5000.
Our normal approach would be to create a TwoBhkHouse
subclass that adds 5000
to the rent
.
We could also have an ThreeBhkHouse
which adds another 5000
to our TwoBhkHouse
.
Now there could be houses with 4bhk and 5bhk as well. If were to continue in the above fashion,
we would need to add FourBhkHouse and FiveBhkHouse subclasses as well, giving us a total of 5 classes.
Using the Decorator
pattern ->
We can start with a decorator called LargeHouse
that can be seen as a wrapper around a House
object.
Extra bedroom houses can now be created by using this wrapper twice on a House
object.
But our implementation has one disadvantage: the has_pool?
method will no longer be available
after decorator has been applied on it. For solving this problem, we can use SimpleDelegator
class in Ruby.
We can implement a HouseDecorator base class from which all our decorator classes can inherit from.
References: Decorator Pattern, SimpleDelegator