Decorator design pattern in functional and object oriented programming

Marco Nicolodi
Apr 1, 2019 · 5 min read

Agile Software Development relies on the ability to change fast. New user stories and enhancements to existing stories are going to happen. Therefore you code will change.

But what about S.O.L.I.D’s Open/Closed Principle ?

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification

The OCP preaches that once an entity is done, it’s done. You should provide them a way to be enhanced/extended.

In Object Oriented Programming this might be achieved with Design Patterns (like Strategy, Template Method), Inheritance, or just good modeling.

In Funcional Programming, otherwise, you could accomplish that with composition, partial application, currying, higher order functions, among other concepts.

Today we are using a pattern supported by both paradigms called decorator.

Definition

Decorators are wrapper functions that enhance the wrapped function. You don’t change the original function behavior, instead you decorate it with new behavior, achieving extensability and composability.

Functional Decorators

Imagine that you are developing a javascript application that runs shell commands through a interactive interface. The user runs a command by pressing a button, and sees the output through a panel.

You create a function to abstract the sometimes complicated spawn/exec Node API. These abstractions are called facades:

Promisified NodeJS spawn facade

This is a promisified facade for the complicated NodeJS spawn API. It accepts two arguments, a shell command string to run, and some options to the spawn native function. It runs the command, prints to stdout, and resolves or reject the promise.

First feature request: print command being run

The users loved the product, but they would like to see what command was issued by them, not just its output.

You can just add a new print.info(command) inside the first line.

The function has two responsabilties now, but that’s ok, really.

But now the function name does not express what it does. It runs AND prints a command.

Second feature request: memoize last command

Users want to have the option to run the last command.

We create a function called memoize(command) that stores the last run command using a persistence mechanism.

We could call memoize before every command call, but then we would add temporal coupling to the commands that need to be momoized, so let’s add this behavior to the runCommand.

This is the result:

This function is doing too much, and getting bigger and bigger. We are going to use the decorator pattern, so we can compose these behaviors without modifying the original function.

Meet the decorator pattern

Decorators are wrapper functions that enhance the wrapped function. There is a TC39 proposal to turn it into an ECMA Script specification. If the proposal becomes a standard, we will have support to decorators as an ECMA Script first class language construct. But since currently it’s just in stage 2, which is the draft stage, we are going to create our own decorators, using Higher Order Functions.

First let’s change our runCommand function to the original version.

Let’s decorate this function with the print behavior. First we create a higher order function that receives a function and prints the first argument. Then we return the decorated function itself:

The withCommandLogger decorator returns a decorated function. We can use it seamlessly as we didn’t know it has been decorated. Notice that we didn’t modify the original runCommand function, which is nice if you want to use it without printing the command being run.

Now let’s add the memoize feature to the command by decorating it again:

Third Feature Request: measure command elapsed time

Now that we know the decorator pattern, it’s easy to enhance the original function without modifying it. Let’s implement the third feature request: measure commands elapsed time. Let’s create the withTimeTracker decorator:

We use the process.hrtime Node API to record high resolution time ellapsed, avoiding some Date API precision drawbacks. Note that this decorator actually executes the decorated function, so it should be the last one to be called.

Wrapping up

Decorator is a design pattern that achieves high levels of extensibility, without modifying the original function. It provides us a way to enhance our functions dinamically, by composition.

runCommand function fully decorated. It’s seamless for the client code if the function is decorated or not.

More generic decorators with rest parameters

You might have noticed that our decorators are coupled with the original runCommand function signature, which expects two parameters. We can make our decorators to enhance any function by using rest parameters:

By using the rest parameter sintax ... the decorators are not aware of the decorated function parameters. They just receive any number of arguments and pass them to the decorated function.

Object Oriented Decorators with C#

In OOP, classes are decorated through inheritance. Decorators extend the decorated class and override the decorated class method or property they want to enhance. The overridden method is enhanced and then calls the super class original method.

Imagine we are developing a first person shooter and we are modeling the weapon object. We should support attaching gadget to modify our weapon damage, bullet capacity and wheight. Our weapon can be rendered and should be able to shoot a target.

We will create an abstract weapon with those characteristics:

We created several fields and properties to describe our weapon, a shot method that deals damage to a target and render method, which is abstract because it’s up to each weapon to decide how it should look.

Let’s create a plasma pistol:

Now we want to add attachments to this weapon. Each attachment may change the weapon’s attributes, and how its rendered. We could use inheritance for that, but we would end up an overwhelmingly complex class hierarchy:

We shouldn’t use inheritance for that

As you can see, it’s not possible to model these attachments with inheritance because we’d end up with a hierarchy mess.

Decorator is a great pattern for solving that.

In OOP, decorators are implemented by inheriting from the decorated class and by receiving a reference to the decorated object in the construcutor.

Let’s create a banana clip attachment to increase our weapon’s bullet capacity by 10 (and therefore its weight):

The decorator also changed how the weapon is rendered. To decorate a weapon with this attachment, we just need to pass the decorated weapon as the decorator constructor argument:

Both vanilla Plasma Pistol and the decorated one are instances of Weapon, so our client code don’t care about the types. Because of that, we can decorate an already decorated weapon, since the decorators inherits from Weapon, just like the Plasma Pistol. Let’s create some other attachments to see that:

Our HollowPoint decorator increases the weapon demage, and our SilencerDecorator renders a fancy James Bond silencer. We can know compose our weapons with attachments, just like Battlefield!

Decorator is a design pattern for dinamically enhancing objects without modifying the original behavior by wrapping, enhancing, and calling the wrappee. What do you think about it, have you found it usefull, or just too pragmatic?

Qualyteam Engineering

Time de engenharia da Qualyteam.com

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store