Design Patterns in Swift: Composite Pattern

Composite pattern is a nice little pattern that will help you manage complex hierarchies. It's commonly used to represent menus and directories/files.

Composite pattern is a nice little pattern that will help you manage complex hierarchies. It’s commonly used to represent menus and directories/files. In this article we’ll go over the theory and learn on an example how to implement this pattern. We’ll use a slightly more colourful example, just to keep you from falling asleep 🙂 In our example we’ll pretend you’re controlling a fleet of spaceships… Let’s play 🙂

Composite Pattern

Like most patterns we covered so far, this one is a brain child of four great developers commonly referred to as the gang of four. This is how they defined the pattern:

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

This can be illustrated with a file system analogy. On our hard drives we have files and folders. Folders contain other files and other folders. We can copy files around, but we can also copy folders. The commands we perform on them are the same, even though the objects are obviously different.

Fleet Example

We’ll use a game as an example in this article. Imagine that you’re playing an online game where you get to control a spaceship. Players can group together in fleets. A fleet will have a hierarchy, with pilots reporting to squad commanders, squad commanders reporting to wing commanders, which report to a fleet commander. In the example we’ll treat a pilot and a commander in the same way. They will all implement the same interface, but they will behave differently. For example, commanders are not allowed to shoot and pilots can’t have anyone reporting to them.

Here is a class diagram of the pattern:

Our fleet will consist of players. A player will be able to perform certain actions (move, shoot…). We’ll have two different types of players: pilots and commanders. A pilot won’t be able to command other players, while a commander will. But, a commander won’t be able to shoot. Only pilots are allowed to shoot. Both, pilots and commanders are allowed to move freely.

We’ll construct a hierarchical fleet that will look exactly like this:

The labels in the rectangles represent the names of the players. Blue rectangles are pilots; red ones are squad commanders; green are wing commanders; yellow is the fleet commander. A commander can command other commanders and other players. Take ‘Redeemer[WC]’ for example. That player can directly control two pilots and two squad commanders. Indirectly he can control seven pilots by issuing commands to their squad commanders.

That diagram looks pretty complex, and you might be thinking how to implement that thing in code. But it’s quite simple. In reality, we’ll only need one protocol and two classes. With that we can build complex hierarchies like the one above.

The Code

Talk is cheap, show me the code 🙂 Let’s start off with the ‘Player’ protocol:

This is the protocol that the pilots and commanders will conform to. We have some properties (name and kills) and some functions. We also have a ‘find’ function that will enable us to search a subsection of the tree… More on that later.

Pilot

The Pilot is the ‘leaf’ on our tree. It has no child objects. It’s a simpler class, so let’s go through it first:

We mostly have print statements here, we don’t have to create a real game, we’re just talking about the pattern here… ‘move’ and ‘shoot’ functions are pretty self-explanatory. Pilots can’t add and remove players, so we implemented a no-op function. We’re ignoring calls to them. You might find the ‘find’ function curious. It just checks if the passed in name is equal to the ‘name’ property of the object, otherwise it will return nil. You’ll see the convenience of this function when we implement the commander.

Commander

Commanders will contain pilots. And, because the ‘Commander’ class will implement the ‘Player’ interface, they will also be able to contain other commanders. This demonstrates the usage of the composite pattern. We have two different objects (commanders and pilots) that are treated equally. Let’s see this in code:

Notice the ‘kills’ property at the top. Commanders can’t kill, so their kill counter will be the aggregate of their team. In the ‘move’ function the commander is proxying the call to all the players it commands. In the ‘shoot’ function we can see how it differs from the ‘Pilot’ class. It has no additional functionality and it’s not incrementing the ‘kill’ property. It’s merely proxying the calls to other players.

Functions for adding and removing players is where the real difference is. We’re adding other ‘Player’ type objects (pilots or commanders) to an internal array. You can see the simplicity of the ‘find’ function here. With this simple implementation we’re searching through an entire tree of objects.

Fleet

Finally, the end 🙂 This is the class that we’ll use to demonstrate the usage of the pattern. A code that creates the fleet that we saw on the diagram above looks like this:

The code above matches the graph perfectly. For example, we can see that the left wing is composed of two squads and two players.

Check out the ‘move’ function that takes in a player name as the argument. We can see that we search for that player using the fleet commander instance. The fleet commander will return an instance of the ‘Player’ type. At this point we have no idea if we’re dealing with another commander or a pilot. We do know that the object knows how to move, so we call the function on it.

Fleet Test

Time to take the fleet out for a spin 🙂 Let’s keep it simple:

We can see from the code above how easy it is to control the entire fleet and subsections of the fleet.

If we moved the player ‘Redeemer[WC]’ the console output would look like this:

We can easily see this player moving his entire wing to the designated coordinates.

Conclusion

The composite pattern has many uses. If you read about it in the books they mostly use the same example of menus and submenus, I wanted to break away from that boring analogy 🙂

When ever you need to represent anything in a hierarchical order you can use this pattern. It would be perfect. Imagine having a fleet of vehicles, the vehicles can be grouped, those groups can have other groups… Once you understand how the pattern works it’s easy to see places where you can apply it.

I hope you’ve enjoyed this article and that you’ve learned something new today. You can find all the code in the GitLab repository along with all the code snippets listed here.

Have a nice day my fellow developer 🙂
~D;

More resources

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.