Design Patterns in Ruby — Strategy

Rachid Calazans
3 min readAug 17, 2018

If you prefer to read this post in Portuguese (Brazil), please click here.

How do I know if Strategy is the Design Pattern you need right now?

If you know that something will always have the same executions, assignments and that there are only variations for certain conditionals, maybe Strategy is for you.

I spoke in a very general way, I know. Let’s abstract for a concrete example.

I need to send notifications to multiple people. What are the duties required:

  • Title or Subject;
  • Content;
  • The list of people I want to notify.

Regardless of how we will send (email or push notification), we will need these three attributes as a minimum requirement.

The variations will come from the way the notification will be sent.

Email -> We will need shipping email;
iOS push notification -> App Token.

For each type, we have a differential, but everything else will be similar.

Strategy is a Design Pattern for behaviours. They are also known as Policy Pattern.

The behaviour of the above example is conditional — for each type of notifier will be treated in a way (behavioural logic) — however, the final goal will always be the same, notify one or more people.

By creating our notifier, we can arrive at the following result:

As we said at the beginning, it only needs to receive :receivers (people), :subject_msg (title or subject) and :content_msg (content of the notification). We have one more required attribute, the :notifier_strategy. It will be the strategy of how we will send the notification.

We expect to receive it in the constructor because we do not want to and do not need to know how it is initialized, we will only know that these notifiers should implement the same #notify method.

A subtlety in the #notify execution of the Strategies is the passing of the context parameter. Strategies will use everything that is necessary for this context. This is a good technique that allows any strategy to use everything from the context without having to make explicit, what is needed for each strategy, and without passing any extra argument.

Creating our first Email strategy:

We note that all other data we need is coming from context, which will be the same for any notification strategy.

Let’s now create a strategy for sending iOS push notification:

For each strategy, the data can be treated differently, just as it was done in IosStrategy above.

We use the same attributes of context, but we put more appropriate names for easy reading and understanding of this strategy.

Beauty, we were able to create our two strategies, let’s demonstrate what their calls would look like.

Conclusion

When we implement the Strategy Pattern we need to remember how interfaces work.

We have seen that in their final execution, it is easy to choose which strategy to adopt and execute.

--

--

Rachid Calazans

💻 Remote Software Engineer at Tidy, 9+xp, 🎙 Podcaster, 📖 Autor, 🙏 Evangelist of TDD and BDD Methodologies linktr.ee/rachidcalazans