Decorator pattern in Swift

Cleaning up your code

Jeremi Kaczmarczyk
Swiftier, faster, better
3 min readNov 12, 2016

--

Let’s work on concrete example from the beginning this time. Just for reference, the classic decorator implementation is based on classes and inheritance. I am going to present Swift way or die trying.

Example

For example if we are to create RPG game in our model layer we could have protocol defining characters in game.

Nothing to fancy. We can use this protocol to create different entities in our game like:

That is no problem right? Well not currently, but as it is a RPG game it can easly run out of control.

Here you have only few Orc structs. Every one of them is separate value which you have to create explicitly. If your game would only contain those three Orcs + John there is no hustle. Above code is ok. But if you consider adding Elves and Dwarves, adding more classed and maybe getMana() function you would be better with the decorator pattern in your toolbox.

The Decorator

The decorator has 4 main actors. Here they are:

  • Core Component — it is the base class or protocol which our base object will subclass / implement. In given example it is Character protocol.
  • Concrete Component — implemetation (or again, subclass) of Core Component.
  • Decorator — again implementation (or subclass) of Core Component. Concrete Decorator has capability of wrapping around Components or other Decorators and building structures. CharacterType protocol is our Decorator here.
  • Concrete Decorator — implementation of Decorator. All structs like Warlord, Mage or Epic are Concrete Decorators.

The Decorator comes handy in following cases:

  • When you have to add new functionality or extend existing in dynamic and transparent way.
  • If you need to reverse changes to objects.
  • If subclassing is inpratical due to big number of subclasses being created in process (that is exactly the case in our code sample).

The main benefit of the pattern is flexibility advantage over just subclassing. In Swift we have different ways like protocols to avoid inheritance but it was the big deal back then. Still when using my struct/protocol implementation it is nice, structured and memory efficent way to organize certain parts of your application. It is also ok to add responsibilities to objects like for example Warlord CharacterType could have Warlord specific function battleCry(). It makes sense.

The Decorator also helps you avoid creating large objects (or values, damn you Swift) with many functions at base level of hierarchy and reduce code repetition. Imagine how much boilerplate it would require to create all classes for all races!

What you have to keep in mind is that objects in Decorator pattern are not the same. They could be but it is safe to be cautious and assume they could be different. Also be prepared for many small, similar files in one way it helps but your project can be easily cluttered by them.

Conclusions

The potential that Decorator pattern adds is clearly visible in example above (in my opinion but whole article is just my opinion). It makes so easy to create complicated structures of similar objects. I mean if you would jump right to the project with me and was tasked to add additional classes and races you can do it just straight away. That is the power of all Design Patterns in general: they simplify communication between programmers. And it is important reason to learn them.

--

--