Design Patterns in life and Ruby – gain an intuitive understanding of OO design patterns by linking them with real-life examples.
The Composite Pattern gives the ability to treat grouped objects and individual objects the same.
Let’s look at its definition:
The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies.
Composite lets clients treat individual objects and compositions of objects uniformly.
A Real Life Example: Group Messaging
Let’s look at the definition in light of group messaging.
1. The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies.
There are six people on my contact list: Mom, Dad, Uncle Bob, Cousin Nick, Aunt Julia, and Amy Kinser. The Parents
group is composed of Mom and Dad, whereas the Uncle Bob’s Family
group is composed of Uncle Bob, Cousin Nick, and Aunt Julia.
In this example, Contacts
is represented in a tree structure made of nodes
. A node is either a group of people or a single person. If a node
is a group of people, like Parents
, then it contains other nodes
. If a node is a single person, like Mom
, then it’s a leaf node
.
Thanks to the tree structure, Contacts
can be arbitrarily complex. For example, I can add another node, CollegeFriends
, containing four friends, two of which are grouped into the Roommates
node.
2. Composite lets clients treat individual objects and compositions of objects uniformly.
We want to message a group of people the same way we message a single person — parents.message(“I’m coming home this weekend :D”)
and mom.message(‘I miss you, mom. ❤’)
.
We can achieve this by having all nodes, both leaf-nodes
and non-leaf-nodes
, support the same interface: node.message(text)
.
The code for leaf-node is straightforward:
class PersonContact attr_reader :title, :number def initialize(title, number) @title = title @number = number end def message(text) puts "Messaging #{title}(#{number}): " puts " #{text}" end end
Let’s send a message to mom:
The code for non-leaf node implements the same interface:
class GroupContact attr_reader :group def initialize(people_in_group) @group = people_in_group end def message(text) group.each do |person| person.message(text) end end end
Let me message my parents:
Woohoo, that’s the Composite pattern!
Takeaways
The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies.
Composite lets clients treat individual objects and compositions of objects uniformly.
Question: may I add you to my contact list? 🙂
Enjoyed the article?
My best content on Software Design, Rails, and Career in Dev. Delivered weekly.
I’m finding more and more where composition comes in handy at work. While I don’t think you should make every class a composition, it should be written in a way it can be converted to it in the future if needed. An example could be adding multiplexing to an instrument data collection. Now a collection of data maybe represented as a tree where the single group of data contains nodes, each of which map to a certain item derived out from the multiplexing.
It was a very useful and informative article. You explained it quite clearly and understandably. Thank you so much.
Thanks! I’ve had wonder for this.. After read your post, Everything is linked..!