Design Patterns: A Software Developer’s Swiss Army Knife

Photo by Patrick on Unsplash

One of the first few computer programs I had to write back in school was sorting a collection of numbers using C. Sorting numbers doesn’t require much thinking — in practice — but there I was tracing and re-writing my code so many times, Ada Lovelace probably tried crossing back to our realm just so she could spare me a few hints out of pity.

Looking back, I wish I had known about sorting algorithms. Regardless of the language used, I could have easily implemented one of them to tackle the problem based on my priorities (memory space, execution time, etc.). But if you think these types of struggles only happen at the beginning of a developer’s career, you’re in for a surprise.

Working in the software industry entails life-long learning. There are always upgrades to technology and tools which end up spawning new problems in place of those they are meant to solve. The game industry gets a fair share of these challenges especially because its market is always on the lookout for something more, and gaming platforms are constantly evolving. At Mighty Bear, we try to balance getting features in as quickly as possible against upholding quality standards for our games’ performances.

One way we do that is to document what’s worked for us before, and constantly see if it can be applied to new problems we encounter. Looking at my first program on hindsight, I realised I could have saved time without sacrificing quality if I had known that other developers already openly shared tried-and-tested approaches like the sorting algorithms I previously mentioned. And this is exactly how Design Patterns started.

Design Patterns were started by the Gang of Four. You can easily google Gang of Four if you haven’t heard about them yet. And no, I’m not talking about the political faction.

The initial set in Design Patterns: Elements of Reusable Object-Oriented Software (1994)

I’m referring to Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides. They did not technically create design patterns; rather, they put together a comprehensive list of common approaches that work for a set of problems. By doing so, the Gang of Four promoted sharing common approaches to solving known problems in the software industry.

Design Patterns don’t just give you solutions, they also offer different perspectives in looking at problems. And since these patterns are language agnostic (meaning you can implement them in any language as long as that language provides the capability needed in the pattern), they are also useful in communicating thoughts without having to go into details. A .Net developer would be able to ask a Java developer to use the Singleton pattern in exposing service classes and the Java developer wouldn’t have to go to a .Net tutorial.

Photo by Tingey Injury Law Firm on Unsplash

Tell me what your problem is, and I’ll tell you which pattern you can use.

Different Design Patterns address different kinds of problem; hence you cannot say that one is better than the other. It is always about what you are trying to solve. Each Design Pattern is a veritable Swiss army knife for developers and the more you know how to properly use each one, the more things you’ll be able to adeptly do with it. Here’s a closer look at one of the patterns which have been frequently useful to me.

Decorator Pattern

The Decorator Pattern is a structural type of Design Pattern. Structural patterns take advantage of the flexibility in forming relationships among objects — in other words, forming a data structure that can address our need.

Decorator Pattern is named as such because… as you may have guessed, it decorates! To further state the obvious, we call an object that decorates: a decorator. A decorator adds functionality to another object. It can also modify or extend an already existing functionality. This pattern reminds me a lot of the Russian Matryoshka doll. You can stack them all around one another, or you can open each one till you have a whole stack of the same dolls.

Photo by Julia Kadel on Unsplash

Here’s a scenario where the Decorator Pattern comes in handy. We’ll set the scene in a game that has superheroes.


We start with a basic superhero who gets to save humankind in an adventure. For every adventure, the player can choose their superhero character and equip it with a special power. For the sake of narrowing down the scenario, we assume that each superhero has a unique speed based on their superpower.


Option A. Technically, it’s possible to add speed and a superpower to each of the SuperHero definitions. That would mean each superhero is activated by changing its superpower and updating the speed attribute once the type is selected.

Option A may work, but imagine how your code would grow over time when more SuperHero types get added to the game. You’d always have to update the SuperHero class, and squeeze as much as you possibly could into a file, thus reducing the maintainability of the code.

Option B. Keep it simple. Start with a hero who has no special attributes.

With the Decorator Pattern, you can treat each superhero type as decorators which add speed and superpower to the initial nondescript hero. Here, you can take advantage of the has-a relationship — IceQueen has-a Hero object, therefore it can access Hero properties. Notice how I’ve also added a new property for IceQueen: defense.

This way, this hero class is independent from the SuperHero code and we can add any character to our Hero at any point in the program by simply doing:

public IceQueen createIceQueen(Hero hero){
IceQueen iceQueen = new IceQueen(hero);

But what’s a game about superheroes with just one character? Here’s ArcadeGuy, peer to IceQueen:

To activate ArcadeGuy, you’d simply have to do this:

public ArcadeGuy createArcadeGuy(Hero hero){
ArcadeGuy arcadeGuy = new ArcadeGuy(hero);

But you are still missing one thing at this point. The scenario needs a flexible solution where your hero can change character for every adventure without breaking the program. So far, we’ve created IceQueen and ArcadeGuy as different hero types, which means that every game flow should have methods that apply to ArcadeGuy and IceQueen whether or not they contain the same logic. However, repeating code only to handle different characters will return us to the original problem surfaced with Option A, where we have to add a new logical flow for every new character we create.

Let’s go back to the Matryoshka doll analogy. We know that a decorator doll is still the same doll, because they look the same! In code, we can do this using inheritance. Inheritance is a feature available in Object Oriented Languages. It lets an object B inherit from object A, its parent. Through this, any method that accepts object A can accept object B because whatever A can do, so can B. However, take note that this relationship is one way. That is, object A can’t be taken as B because the child class, B, may have extended features that aren’t available in its parent, A. This time, we take advantage of the is-a relationship: Object B is-an Object A.

To achieve this step in our example, we create a superclass for all our heroes. This parent class will determine the basic property of a hero. By making our parent an abstract type, we ensure that it cannot be instantiated and that the inheriting class are forced to provide custom implementation to the properties.

Recall how our superhero constructors accept Hero as parameter. By making our SuperHero and Villain inherit from Hero, we can now spin up different characters from either a SuperHero or SuperVillain.

SuperVillain superVillain = new SuperVillain();
IceQueen villainIceQueen = new IceQueen(villain);

SuperHero hero = new SuperHero();
IceQueen heroIceQueen = new IceQueen(hero);

Now, let’s take our character shifting further: a wild request comes in where we need to have a combination of both IceQueen and ArcadeGuy’s superpowers! Similar to what we’ve already done, we can use inheritance to make it possible by setting up a parent class for all decorators. We again extend Hero to make sure every decorator can still be recognised as Hero.

At this point, adding new characters is possible without changing anything from the classes we have already setup. We can even decorate our superhero or villain with as many superpowers as we want!

SuperVillain villain = new SuperVillain();
//I want my super villain to have both IceQueen and ArcadeGuy Powers
Hero iceVillain = new IceQueenDecorator(villain);
Hero iceArcadeVillain = new ArcadeGuyDecorator(iceVillain);

//Output: Evil Laugh and Freeze and Wreck

You can do this and more with the Decorator Pattern. This pattern has also helped me in achieving backwards compatibility and adding methods to data objects that I can’t change internally, among other use cases. Just remember the two handy features: is-a and has-a, and your perspective’s the limit!

I hope my sharing of this pattern has decorated you with an appetite to check out other patterns! As you may have figured, there have been many more new patterns that have emerged after the Gang of Four’s initiative. We’re always looking for more efficient and innovative ways to work at Mighty Bear, and periodically share our findings via our Medium publication. Follow us if you’d like to learn more, and as always, we’d love to hear your thoughts in the comments.

Design Patterns: A Software Developer’s Swiss Army Knife was originally published in Mighty Bear Games on Medium, where people are continuing the conversation by highlighting and responding to this story.