Go — Composite Pattern. Composite Pattern falls under…
By: Haluan Mohammad Irsad
Tags: Software Engineering, Software Development, Software Design Patterns, Composite Pattern, Golang

Prerequisite

Before reading this article, make sure you have a good understanding of Go Interface.

Introduction

Composite Pattern falls under Structural Design Pattern. Based on the book Design Patterns [Gamma et al.], the intent of this pattern is:

Compose objects into tree structures to represent part-whole hierarchies. Compositelets clients treat individual objects and compositions of objects uniformly. — Design Patterns [Gamma et al.] p. 163

This pattern is effective to dynamically compose a structure of objects. The easiest way to describe it by imagining a set of objects composing a hierarchy. For example, it can be a hierarchy of an organization.

In this article you will learn:

How to implement basic composite pattern to build the organizational hierarchy

How to reuse the composite pattern for another hierarchy problems

Implementation

We start this journey with our fictional friend, Kant a programmer in an online shop company. He has a task to create an organizational hierarchy of the company.

Kant starts to write Component Interface, this is the foundation of his code:

Then, he continues to create the Employee model which inheriting Component interface:

For simplicity, we will use a console print and simplify the input by directly hard code the values. Also, we can ignore success/error (result, error) pattern that usually being used in Go.

After Kant wrote the Employee model, he starts to write the Composite struct. This struct became the base-ground for hierarchy definition. Kant realized, the organizational hierarchy can be treated similar to a Tree data structure, so he creates the logic for add and displays people to the organization as shown below:

Let’s take a breath for a moment because I will explain what Kant did there.

type Composite struct {

component Component

leaves []Component

}

As we saw, Composite struct has two attributes:

component: The root of the Tree/Head of the organization

leaves: The leave of the Tree/Subordinate of the organization

Also, pay attention to this code:

func (c Composite) Display() {...

That code will make Composite struct inheriting Component interface.

Also, Kant just realized in the company which he working, there are so many divisions and each of the divisions might have sub-divisions.

Company Hierarchy in a simple way

So he starts to build the composition of company hierarchy as shown below:

What Kant did:

Build the hierarchy of office of VP of Idealist

Build the hierarchy of office of VP of Realists

Build the hierarchy of the company, by adding the Ceo and add two offices of Vice Presidents

As we remember, in composite.go we have Display() :

func (c Composite) Display() {

c.component.Display()

if len(c.leaves) == 0 {

return

}

fmt.Println("===List of Subordinates===")

for _, leaf := range c.leaves {

leaf.Display()

}

fmt.Println("===End===")

}

So, that method will iterate and print component and leaves from:

VP of Idealist

VP of Realist

CEO (company level)

If we run composite.ShowEmployeeHierarchy() in main.go , the result will be:

Office of VP of Idealist:

=====Display Office of VP of Idealist=====

ID: ID-2

Name: Plato

===List of Subordinates===

ID: ID-4

Name: Hegel

===End===

Office of VP of Realist:

=====Display Office of VP of Realist=====

ID: ID-3

Name: Aristotle

===List of Subordinates===

ID: ID-5

Name: Hume

===End===

Office of CEO:

=====Display Company=====

ID: ID-1

Name: Socrates

===List of Subordinates===

ID: ID-3

Name: Aristotle

===List of Subordinates===

ID: ID-5

Name: Hume

===End===

ID: ID-2

Name: Plato

===List of Subordinates===

ID: ID-4

Name: Hegel

===End===

===End===

Reusability

After Kant finished his task, his PM came to him and asked whether he can build the shopping item catalogue in a hierarchical fashion. The deadline is in 30 minutes. Maybe for some programmer other than himself, will protest the deadline. But, because this Kant, our beloved programmer, he just nodded and turn back his face to his computer with a smiley face.

As we remember, Kant already create composite.go which is the solid solution to solve the shopping item catalogue.

One thing which he needs to do just only composing the product catalogue, let’s abstract this to be like:

ItemCategory model

This model is inheriting Component interface.

ShoppingItem model

This model is inheriting Component interface.

Composing the Shopping catalogue

This code is very straightforward by reusing composite.go .

Then before 30 mins were overdue, Kant called his PM. His PM and team applaud him because of his quickness to accomplish a new task.

Conclusion

After we observe what Kant did, we can get a lot of benefits by implementing Composite design pattern.

We get adaptability, the code has a clear path to define the hierarchy. By utilizing the interface, we can hide the implementation detail of the code to make it become adaptive to changes.

We get reusability, the code can be reused to another problem. As long as the problem has a similar pattern.

We get agility, the agility is an important point for software development. We have adaptive code and reusable component, it will give us advantage overtime, by avoiding reinventing the wheels every time there is a new feature which has a common problem with what we’ve been done yesterday.

The Composite pattern can be combined with the Decorator pattern.

When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild. — Design Patterns [Gamma et al.] p. 173

The benefit of using a design pattern, we can consolidate one design with another design, and it will give us a rich benefit exponentially in adaptability, reusability, and agility.

By defining fine-grained code and reusable components, team productivity can be increase exponentially to create a new feature for the benefit of the company.