If you’re going to apply for a coding job for an object oriented language, there’s a chance that you’ll be asked about the decorator pattern.
Decorator Pattern Definition
So what exactly is the decorator pattern? A dead simple explanation of the decorator pattern is that it allows you to add functionality to a specific object instead of an entire class of objects.
When working with the decorator pattern you may feel like you’re using plain old object oriented inheritance. However there is a key difference. While inheritance typically is used when a class is a sub type of a parent class, decorators are used when we simply need to pass some custom behavior to a specific set of objects.
If this still seems a bit fuzzy, don’t worry, we’ll dive into an easy to understand code example.
Decorator Pattern Code Example
Before we get into decorators, let’s start by looking at classic object oriented inheritance. In this program we have two classes, a
User class and an
Admin class. The
Admin class inherits from
User and overrides the default
If we run this code everything works properly. New users have a greeting that says “welcome to the site” and admins are informed that they’re on the admin dashboard.
This code is setup properly because an
Admin is a type of
User. This is classic object oriented inheritance.
Using a Decorator
But what happens when we want to add some custom behavior to our
User class, such as users that are on a trial membership?
Imagine that you have a site like Netflix where you give users the ability to sign up for a trial account. Technically we could create a new class called
TrialUser and have it inherit from
User. However a trial user isn’t really a type of user. It’s simply a stage where the user is at in the sign up process.
This is a good example of how we can use the decorator pattern and give custom behavior to users that are currently in the trial stage.
In this Ruby code I’ve created a module called
TrialUser. Inside of the module I’ve added a custom
greeting method that returns a greeting specific to users on a trial membership.
From here I can create a new
User just like I would normally. However, notice how I’m using the
extend method and passing in the
TrialUser module? This tells Ruby that slide the
TrialUser module in as a layer of our new
From here I can call the
greeting method and it will print out the custom greeting that we created for trial users.
Items to Notice
This is a great way to customize the behavior of objects without cluttering classes with unnecessary code. You should also notice a few other key items:
- Our decorator is not affecting all users, only the specific user that it’s being layered on.
- It’s also important to notice that our decorator has access to the instance variables set in the
When to Use the Decorator Pattern?
So when is it a good idea to use the decorator pattern in a program?
There are a few scenarios where decorators are preferable over inheritance.
- In scenarios like our example where we need to customize an object that does not fit the
is atest required for inheritance.
- Using decorators is considered a best practice when it comes to rendering view code. Instead of hard coding server side code inside of HTML files, decorators can be leveraged to streamline front end templates.
- Decorators are also popular if you work with streams in frameworks such as .NET.
I hope that this has been a helpful guide to understanding the decorator pattern. Decorators have been around for decades and have unique implementations in each language. The example I provided in this guide was one of four popular ways to implement decorators in Ruby. In the resources section of this guide I’ve linked to additional posts that you can check out to deepen your knowledge on the subject.