The Decorator Pattern is one of the most abused and misnamed patterns in all of patterndom. It has deep roots in the patterns movement on the c2 wiki, and found its way into the Gang of Four “Design Patterns” book. Unfortunately, the misuse of the pattern name in modern, dynamic programming languages has created some really crappy designs.
Take, for example, the use of the pattern name in Spree, the open-source e-commerce platform built on Rails.
In Spree, there is some meta-require magic that loads files with names ending in
_decorator.rb after all of Spree’s models are loaded.
You can see in the user’s guide that coders are encouraged to open up the class and add new methods to a model like this:
Spree::Product.class_eval do def some_method ... end end
Or on a controller like so:
Spree::ProductsController.class_eval do def some_action ... end end
Then, elsewhere in the application, you can call your new method like this:
Too often, when someone uses the pattern name “decorator,” they are simply adding methods to existing classes. Unfortunately, that is not actually what a decorator is.
This pattern abuse causes a significant design problem. In order to use the new method, the caller has to know that it has the decorated class and not the original class. Because the caller needs to know something about the "type" of the instance it’s using, the new class is not substitutable for the old one. We have a design principle that gives us a name to this problem. This is a violation of the Liskov Substitution Principle (LSP).
So why do coders misuse and misname the Decorator Pattern? The problem is with the pattern name itself and how you interpret the metaphor “decorate.” I like to think of this metaphor like decorating the interior of a room. If the class is a room in a house, then the methods are like the furniture, rugs, carpet, and curtains. When you decorate a room, you might bring in a new rug. This is parallel to adding methods to the class. This interpretation leads coders astray. “I could use a new method,” we think, "so I’ll just decorate this bad boy.”
What if we shifted the granularity of the metaphor just a bit? What if the class is like the entire house? The methods would be like the rooms in the house. Adding a room to a house is a lot bigger deal than adding a rug. If you keep adding rooms to your house, then you end up with something that looks like the Weasley's Burrow from Harry Potter. If rooms are like methods, then decorating a method means changing or adding to the behavior of that method, not building on an addition.
The second interpretation of the metaphor is more accurate with respect to the definition of the Decorator Pattern. Let’s take a look at it.
It’s an odd class diagram. The decorator both contains and implements the class being decorated. You can change the behavior of a closed class without modifying that class. The decorator is 100% substitutable for the original class. It’s a careful implementation of the Liskov Substitution Principle.
The idea is that as you implement the decorator, you call the original behavior on an instance of the original class, then do your own thing before or after doing that. Logging is one of the classic examples. If you don’t want to pollute a class with a dependency on logging and a bunch of log statements, then you can wrap a decorator around it that logs first, before calling the original method on an instance of the original class. The decorator is then injected everywhere the original was used.
def initialize(original) @original = original end def do_the_thing log.info "I’m doing it!" original.do_the_thing end
The truth is, the mechanics of this pattern are obsolete in dynamic programming languages. We simply don’t need the ceremony of the two instances and the inheritance structure to pull it off. We can just open up the class and change it. Here is where we have to be careful though. We don’t want to change the public interface of the class we are modifying. We don’t want to add any new methods to our class; we just want to decorate the ones we already have.
In Ruby, we used to do it this way:
MyClass.class_eval do alias_method :original_do_the_thing :do_the_thing def do_the_thing log.info "I’m doing it!" original_do_the_thing end end
Here you alias the original method to a different name, then implement a new method and call the old method from inside it.
Ruby recently added prepend, which does this much more cleanly.
module MyClassExtensions def do_the_thing log.info "I’m doing it!" super end end class MyClass prepend MyClassExtensions end
Either of these language features can accomplish the modification of behavior that the inheritance structure in the pattern definition does for static languages.
So what’s the big deal? I know that I am arguing over semantics. But in coding, names matter a lot. When you leave behind a code base for others to modify, your names are one of the few traces of your original intent that you have to leave behind. Perhaps we can come up with a new name for the pattern where you open up a class and hang new ugly methods off of it? How about the Remodeler Pattern? Maybe the severity of that name will prevent you from wanting to open up a class and add new methods. Whatever you call it, please don’t call this resulting monstrosity a decorator!