Following up from yesterday’s purchase of Clean Ruby by Jim Gay, and in preparation for tomorrow morning’s AirPair with Edward Anderson, I decided to read up on the composite pattern. This post comes from my reading of chapter 6 in Design Patterns In Ruby by Obie Fernandez.
The Whole and it’s Parts
Here’s an excerpt from his book to kick things off.
Building object-oriented software is the process of taking relatively simple objects, and combining them into slightly more complex objects. We can then use the resulting objects to build even more interesting objects. What usually emerges at the end of this process are a few very sophisticated objects that look nothing like the component bits and pieces that we used to assemble them.
He states in a following paragraph that we can think of the process of turning simple objects into more complex ones as a tree, where the master task of the program’s purpose (i.e. Obie uses a cake manufacturing program as an example) is built up from subtasks such as baking and packaging the cake, which are themselves made up of even simpler tasks.
What is a Composite Pattern Anyway?
The GoF book calls the design pattern for a “the sum acts like one of the parts” situation the Composite Pattern.
Here’s what wikipedia says about the composite pattern:
In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects are to be treated in the same way as a single instance of an object. The intent of a composite is to “compose” objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
To build the composite pattern we need three moving parts.
- A common interface or base class for all of your objects
- One or more leaf classes
- Ate least one higher-level class, called a composite class
#1. A common interface:
When thinking about the design of a common interface, we should think “what will my basic and higher-level objects all have in common?” This is considered an interface or base class of the component.
#2. Leaf classes:
These are the simple, indivisible building blocks of the process. If we were making a pizza, you could consider each ingredient (i.e. cheese, tomato sauce and flour) as a simple enough division to be considered a building block. These indivisible leaf classes should implement the component interface. For instance, a higher level component could be ingredients, preparation, creation, packaging, and delivery.
#3. Higher-Level Class:
We need at least one higher-level class, which will be considered the composite of the leaf classes we went over above. The composite is a component, but its also a higher-level object that is built from subcomponents in a manner consistent with the law of demeter. Worded a little differently, composites are just complex tasks made up of subtasks.
The Composite Pattern in Action
I’m going to use the same examples that I read in Design Patterns in Ruby, because its just very well written, and I understood it well the way Obie laid it out.
Here’s an example of a component base class:
Task class in considered an abstract base class in the sense that its not really complete: It just keeps track of the name of the task and has a ‘do-nothing’
Two leaf class examples are up next:
These are a couple of the simple, indivisible building blocks of the process.
And here are two ways to build our composite class:
Because we will have a number of composite tasks in our baking example (packaging a cake as well as the master task of manufacturing a cake), Obie states that it makes sense to factor out the details of managing the child tasks into another base class, like so:
Obie says that the key point to remember about composite objects is that the tree may be arbitrarily deep. While our
MakeBatterTask class goes down only one level, this isn’t typically the case.
Any one of the subtasks in our illustration above may be a composite also, like our
MakeBatter class from our 3rd illustration above.
I have to first off say that being at the foot of a set of stairs that will have my writing and thinking about code in this manner is something I consider extremely exciting! It is also a bit overwhelming to take in, but thats what practice and communication with others is for!
If you haven’t paired with someone before, or even if you have and enjoy hearing extremely intelligent people communicate effectively. Have a look at this video, it’s the one that introduced me to the concept that ‘paring is caring’.
May your week be productive and fun!