During a recent interview I asked the candidate about their understanding of design patterns. I was impressed not only with their honesty, telling me they only had basic knowledge, but also with their description of the Singleton pattern:
It's like Highlander … there can be only one.
Since then I discovered that there are already some memes floating around with the same joke, but it made me chuckle anyway. It got me thinking that perhaps there is something in the idea of using pop culture references to remember the fundamental goals of design patterns.
This series is my attempt to choose some good references. It's not to be taken too seriously, and I won't provide in depth explanations of each pattern as there are already amazing sites for this like https://refactoring.guru.
Let's try creational patterns first. Here goes …
Image sourced from: https://www.vintagemovieposters.co.uk/
Singleton ensures that only one instance of the class which implements it can exist. Global access to that object can be used within state management applications (think Redux).
If you haven't seen The Highlander, you're missing out. I love it, even though it's 80s cheese. Immortals battle it out to be the only immortal, because just like the Singleton pattern 'THERE CAN BE ONLY ONE!'.
Other similarities between Singleton and The Highlander:
- They're both classics, and both much criticised. I'm not afraid to say that I love both of them - I can still remember my first time implementing a Singleton.
- In The Highlander, after beheading another immortal, all knowledge that person has obtained during their lifetime is transferred to the surviving immortal in a process called The Quickening. One of the criticisms of Singleton is that it can be used as a global store for everything, resulting in separate components of an application knowing too much about each other.
Image sourced from: https://www.timeout.com/
The goal of the Builder pattern is to construct complex objects, and allow you to create variations on those objects using the same code.
A frequently used analogy for this pattern is assembling a meal in a fast food restaurant. My somewhat limited imagination allowed me to think of Five Guys. Think of making a burger as a complex task - implement the Builder pattern to call:
AddPickles() AddBacon() AddCheese() AddKetchup()
Obviously if those are your only choices of Five Guys burger toppings something has gone wrong, but hopefully you get the idea.
Builder also has an optional implementation of a Director, further abstracting the implementation and simplifying things for the client. This is like your Five Guys cashier who takes your order for a burger all the way, and a crazy milkshake with 11 mixins, and then sends all required instructions to the builder team who assemble and deliver your meal.
Image sourced from: https://www.assignmentx.com/
The Prototype pattern is used to remove complexity from copying objects. Objects that implement the Prototype pattern know how to clone themselves, so code that needs to make a copy does not need to know the complexity of the class.
In Benderama, Bender makes clones of himself. Unfortunately each clone is smaller than the previous one and when they reach molecular level they nearly destroy the world. Obviously knowing that detail this analogy falls down entirely.
Image sourced from https://abcnews.go.com/
Factory Method provides a way for a class to create similar objects, but to leave the individual subclasses to use their own logic. This is done by defining an interface implemented by all subclasses so individual objects can be created using common methods, but without knowing the details of what's inside.
First of all, in case you don't know what it is, the Pepsi Challenge is a marketing campaign from the 1980s where shoppers would do a blind tasting of Coke and Pepsi and say which one they preferred.
Why is Factory Method similar to the Pepsi Challenge? Think of an abstract class called
SoftDrink which provides a creational method.
And an interface implemented by every soft drink providing the following common methods:
FillBottle() OpenBottle() PourDrink() DrinkCola()
This is Factory Method! The creational logic of each drink is the secret recipe closely guarded by Coke or Pepsi. When the consumer takes the challenge, they call the
DrinkCola() function but they do not know if they are doing that for Coke or Pepsi, thanks to the Factory Method which hides that complexity (in the form of a big yellow box).
Using this approach, Pepsi could add as many drinks as they want to into the challenge. They don't really need to do that though, as instead through shameless capitalism the two companies have successfully wiped out or bought out most other competition.
One drawback of the Factory Method is that requires implementation of many subclasses. This can make quite a simple concept harder to understand than intended when actually implemented, just like my attempt to use the Pepsi Challenge to explain this pattern.
Image sourced from https://about.ikea.com/
You may guess from the name that this one adds a layer of abstraction to the Factory Method. It is used for creating groups of related objects (a family). The Abstract Factory class holds a bunch of abstract creation methods which know how to create instances of the objects. Concrete factories will then be called to actually create the object.
Think of each family like a set of matching furniture from Ikea. The furniture family might contain a chair, sofa and a table. Different style chairs would have the same chair interface, the
create() method would implement the style of that chair's given family. The factory for a given family will call the specific
create() methods to create each furniture type with the correct style matching the family.
I'm sorry to say that I had a lack of imagination for this one, and the chosen analogy is the same as several other examples online. One of those is the excellently written article on https://refactoring.guru/ which has a great explanation. I recommend that you spend some time reading that, and hopefully the Ikea link will start to stick.
And there you have it, hopefully some memorable references for Singleton, Builder, Prototype Factory and Abstract Factory creational design patterns.
Look out for further posts in this series where I will try to do the same for structural and behavioural patterns.