by andrew

Design patterns: composite

While describing iterator pattern on previous post I mentioned it was a part of a bigger chapter in the Head First: Design Patterns book. The second design pattern described in the chapter is called composite. The composite pattern helps us create tree structures in our code. The book example this time is pretty straight-forward but the end of it shows the power of iterator and composite together.

Book example

We’re still with our merged restaurants. It’s easy to add more restaurants and merge their menus into one. We have our iterators to traverse through all menus and print them. But just when we thought it was safe we received a request we hadn’t expected: they want us to implement sub-menu.

The time has come to refactor all the code we’ve created so far! We’ve reached a level of complexity such that if we don’t rework the design now, we’re never going to have a design that can accommodate further acquisitions or sub-menus. Is the composite pattern the direction we should follow?

The Component defines an interface for all objects in the composition: both the composite and the leaf nodes. It may implement a default behavior for add(), remove(), getChild() and its operations. We’re going to implement MenuComponent in this place.
The Composite‘s role is to define behavior of the components having children and to store child components. In our implementation Menu class will become composite.
The Leaf defines the behavior for the elements in the composition. A leaf has no children. MenuItem class will be our leaf class.
Note that composites (Menu) and leaves (MenuItem) implement operations which may not make sense (for example implementing add() method in MenuItem class) so in that case an exception might be generated. That’s why we start with the MenuComponent class which is rather simple:

The constructor and getters don’t change at all so I removed them from the listing above. The only changes are:
the class inherits now from MenuComponent and I added getListing() method which returns a string with all information connected to the menu item. All other methods inherited from MenuComponents will throw an exception if used on MenuItem instance.

It has less properties (and getters) but one of the properties is very important: $menuComponents. Within it Menu stores all its children. This class overwrites methods connected to children operations: add(), getChild(). We don’t want now the functionality of removing, so we just not overwrite the method here (it’ll throw an exception from MenuComponent class).

And this is the place (getListing() method of Menu class) where we use learnt earlier iterators. Thanks to the fact that we iterate through aggregates with Menu and MenuItem instances and they both implement print() method we’re sure the code is solid and does what we want — it prints all elements: menus and menus’ items.

We don’t need the method which we pass menus’ iterator to. All we need is to recursively get all menus listed by calling getListing() on the top element and then print its results on the screen.

And this is the end of our refactoring. The chapter in the book continues with explaining why the design principle learnt in the same chapter wasn’t followed this time. Surely, the composite pattern manages hierarchy and it performs specific operations related to leaves. Of course this is a phenomenon which happens quite often in software development — classic case of tradeoff. We can say Signle Responsibility design principle is being trade for transparency. Transparency which makes the client treat leaves and composites uniformly. An example composite application can be as always downloaded here.

Other examples

Nice example of composite pattern is described by Craig Sefton on his blog. Craig describes how to use the pattern to be able to create not only one-level-flat lists from our real life.
Basically, that was my thought that composite is a great way to handle complex lists. And what are lists used for on the Internet? Menus! Probably there are lots of menu implementations using composite pattern. Maybe I’ll check it later

However, not only such simple components as menus can be handled by composites. Few years ago I learnt that Symfony 1.4 used decorator pattern for their views system. While looking for examples of composite pattern usages I’ve found very nice articles by Alejandro Gervasio. He describes there the mentioned way but also the other way: using composite design pattern to create view system!
Mentioning Symfony and more complex systems build with composite pattern, Hugo Hamon, presented practical usage of design patterns during this year PHP Benelux. You can see on his presentation composite used to build form builder.

I think these examples proves how useful the composite design pattern is. Sometimes, we have to make this tradeoff in favor of transparency.