melreams.com

Nerrrrd

Strategy pattern

Let’s talk about the strategy design pattern today. According to good old wikipedia, the strategy pattern “defines a family of algorithms, encapsulates each algorithm, and makes the algorithms interchangeable within that family.” In other words, if you have an object most of its behaviour stays the same but there’s one piece that changes, you want to be able to change that one piece without messing with the rest of the object.

A concrete example would probably help :) Let’s say you’re working on a videogame with monsters that attack the player and you want your monsters to be more aggressive at night and less aggressive during the day. The rest of the monster code like movement and tracking health points or inventory stays the same, it’s just one part of the behaviour that you want to be able to change on the fly. The strategy pattern would let you swap in different “should I attack the player?” algorithms any time and the monster code wouldn’t have to change, it would just call a method on the strategy object it was given.

So how would you implement the strategy pattern? Pretty much the same way you’d implement the bridge pattern, actually. The bridge pattern is about organizing your code and the strategy pattern is about how it behaves (thank you stackoverflow), but the way you arrange your interfaces and objects that inherit from them is largely the same. One difference is that your context class (the one that uses the strategy for something) doesn’t have to change – you could have only one of those and still want to use the strategy pattern. Comparing the class diagrams for the two patterns helps show how similar they are.

Here’s a class diagram for the strategy pattern:

Diagram taken from wikipedia, by Bocsika - wikimedia, CC0
Diagram taken from wikipedia, by Bocsika – wikimedia, CC0

and here’s one for the bridge pattern to compare it to:

By Trashtoy - My own work, written with text editor., Public Domain
By Trashtoy – My own work, written with text editor., Public Domain

If you imagine there’s another ConcreteImplementor, the bridge pattern looks a lot like the strategy pattern. On it’s own I don’t find the bridge pattern diagram super helpful, but in comparison with the strategy pattern diagram it does help illustrate that there are more things that vary in the bridge pattern than in the strategy pattern.

Given that the patterns are so similar, why do we need both of them? Earlier I mentioned that the bridge pattern is about organizing your code and the strategy pattern is about how it behaves. That might sound like a minor difference, but misunderstandings are a huge, huge problem when you’re developing software. It really does help to make it as clear as you can when you’re talking about how you want to arrange your code and when you’re talking about how you want it to behave.

Bridge design pattern

It’s design pattern time again! This time, let’s talk about the bridge design pattern. The bridge pattern is officially meant to “decouple an abstraction from its implementation so that the two can vary independently” which is just all kinds of helpful. The design patterns book has a lot of great ideas but they’re not always communicated especially clearly. That definition of the bridge pattern sounds an awful lot like the adapter pattern, which is meant to “convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.”

First let’s talk about what the bridge pattern actually is and then we can get into how the bridge and adapter are different.

The way I would define the bridge pattern is it decouples multiple abstractions so they can both vary without making a huge mess. Maybe that’s clearer and maybe it’s not, so how about an example. I’m going to steal John Sonmez’s web app type and theme example from his post on the bridge pattern. Let’s imagine we have a web application framework that we can base different applications on, like a blog or a news site or a store. That’s one abstraction. Now let’s imagine we want to add themes. That’s another abstraction. When we first start building themes, it’s tempting to subclass our first abstraction, the web app type, for each theme. If we have two themes, say light and dark, we end up with six subclasses: blog-light, blog-dark, store-dark, store-light, news-light, and news-dark. That’s kind of a mess, and it’s only going to get worse when we add more themes and more app types.

What would be a lot cleaner is if we separated app type from theme so they can each vary without requiring an explosion of subclasses. If theme was separate from app type and each app type had a theme (composition over inheritance!), we could add all the themes we wanted without having to create any more app type subclasses.

Or to put it another way (ascii art diagram also by John Sonmez):

When:

        A
     /     \
    Aa      Ab
   / \     /  \
 Aa1 Aa2  Ab1 Ab2

Refactor to:

     A         N
  /     \     / \
Aa(N) Ab(N)  1   2

Instead of having one complicated hierarchy, sometimes it’s easier just to have two simple hierarchies.

Hopefully the bridge pattern makes sense now. On to the adapter!

The adapter pattern has a really simple real-world analog -it’s the object equivalent of the power plug adapter you use when you travel to a country with different wall sockets and you want to be able to plug your laptop in.

For a more codey example, imagine you have an application that notifies the person on call when a status check fails or something weird happens in the log. Depending on how urgent the event is the app either sends an email, a text, or a phone call. The code that decides a notification should be sent shouldn’t know about the details of sending texts vs making phone calls, it should be able to give the notifier class a recipient and a message and be done with it. The problem is that the libraries used to send texts and phone calls and emails all have different interfaces and that makes our code a mess. To clean it up, we use the adapter pattern (also known as a wrapper) to make the interfaces to each of those libraries look the same. That lets us use each library without having a big ugly if statement with slightly different method calls for each type of notification we want to send.

The adapter and bridge patterns are pretty closely related and it’s not unusual to need both of them. In the web app type and theme example above we didn’t get too far into implementation details, but if we wanted to add a theme created by someone else we might need an adapter to fit the new theme into our existing bridge pattern.

The Visitor design pattern

Let’s talk about the visitor design pattern. This one is tough to find a real-world analog for, but once it clicks for you it can be really useful.

Basically the visitor pattern is used when you want to add functionality to an object or a set of objects without changing the object itself. If you have a list of objects and you want to perform a particular calculation on each one and might need to add more calculations later, you would use the visitor to ‘visit’ each one, get its state, and do the calculation. Headfirst design patterns uses the example of a menu item and an ingredient both needing a nutrition information report. It’s ugly to add essentially the same method to two classes and it violates the single responsibility principle to add a method that does something the base object shouldn’t know about.

Uncle Bob uses the example of building a report with data from hourly but not salaried employee objects. The employee object shouldn’t know anything about how to generate a line for that report or even whether it should be on the report at all, so it’s much cleaner to use a visitor to get each object’s data and use that to build the report.

So how does the visitor pattern actually work? First of all you need some interfaces or abstract classes for your other classes to inherit from. To keep using Uncle Bob’s employee example, you need an employee interface with an accept method that takes a visitor interface/base class as a parameter. Your visitor interface needs a visit method for each type of object it’s going to visit. Now that you have your interfaces set up, concrete employee classes like SalaryEmployee and HourlyEmployee can implement the accept method. All you need to do there is call visit(this) on the visitor that was passed in. Your concrete visitor class just needs to implement visit methods for each visited object and you’re done! There’s a nice clean class diagram here in case seeing it makes it easier to understand.

Why so many interfaces? Wouldn’t it be simpler just to call methods on the concrete objects directly? Not so much. We need an accept method on the employee interface so that the code that iterates over your list of employees and calls accept(visitor) on each one doesn’t have to know what type of employee it is. We need a visitor interface separate from the concrete class/es so that we can add more visitors without having to change the visited objects and because the visited objects shouldn’t be coupled to the visitor object. In the report example, the employee objects shouldn’t know anything about the visitor that compiles the report. To put the single responsibility principle another way, the report just isn’t any of the employee object’s business. If we decide to change the way that report is calculated or add another version of it, the employee object shouldn’t know or care.

Why not put the accept(visitor) method in the employee base class? Because then it would only be able to pass an Employee to the visitor, which is no good if different types of employees need to be treated differently. Yes, it’s duplicate code, but only a tiny little of it and in this case it’s necessary.

Aside from keeping your base objects from having multiple responsibilities, another thing the visitor pattern gives you is one class where all the related methods live. To stick with the report example a little longer, we’ve got all our report logic in one place instead of scattering it over different classes. Yay single responsibility! If we decide to change how we calculate rows in that report, we only have to change one class. If we only have two types of employees that may not sound like a big gain, but what if we need to add contractors and consultants and seasonal employees and part time employees?

The visitor pattern is a really weird concept at first but once you understand it, it can make your code a lot cleaner.