The Power of Composite Pattern in JavaScript
Tags: javascript, node, webdev
Published: 2019-12-11 04:01:38

Find me on [medium](https://medium.com/@jsmanifest)

In this post, we will be going over the _Composite Design Pattern_ in JavaScript. In software engineering, the composite pattern is a pattern where a group of objects is to be treated in the same way as a single instance of a single object--resulting in uniformity with these objects and compositions.

The intentions of a composite is to _compose_ multiple objects into a certain [tree structure](https://en.wikipedia.org/wiki/Tree_structure). This tree structure represents a _part-whole hierarchy_.

In order to understand the composite pattern in greater detail we'd have to understand what a part-whole is and what it would look like in a visual perspective.

In terms, a part-whole relationship is basically where each object in a collection is a _part_ of the _whole_ composition. This _"whole"_ composition is a collection of _parts_. Now when we think of a part whole _hierarchy_, it's a tree structure where each _individual_ "leaf" or "node" is _treated the same_ as every other leaf or node in the tree. This means that a group or collection of objects (sub-tree of leafs/nodes) is also a leaf or node.

In a visual perspective, an example of that can end up looking something like this:

![composite pattern visual perspective in javascript](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/composite+pattern+visual+perspective+in+javascript.jpg)

Now that we have a clearer understanding of the part-whole concept, lets go back to the term _composite_. We said that the intentions of a composite is to _compose_ any of these objects (leafs/nodes) into a tree representing this concept.

And so the composite design pattern is where each item in a collection _can hold other collections_ themselves, enabling them to create deeply nested structures.

## The anatomy

Every node in the tree structure _shares a common set of properties and methods_ which enables them to support individual objects and treat them the same as a collection of objects. This interface promotes the construction and design of algorithms that are recursive and iterate over each object in the composite collection.

## Who is using the pattern?

Operating systems use the pattern which in turn led to useful features like allowing us to create directories inside other directories.

The files (we can refer to anything inside a directory an _"item"_ at this point which makes more sense) are the _leafs/nodes_ (parts) of the whole composite (the directory). Creating a sub-directory in this directory is also a leaf/node including other items like videos, images, etc. However, a directory or sub-directory _is also a composite_ because it's also a collection of parts (objects/files/etc).

Popular libraries like React and Vue make extensive use of the composite pattern to build robust, reusable interfaces. Everything you see in a web page is represented as a _component_. Each component of the web page is a leaf of the tree and can compose multiple components together to create a new leaf (when this happens, it's a _composite_ but _is still a leaf of the tree_). This is a powerful concept as it helps make development much easier for consumers of the library, in addition to making it highly convenient to build scalable applications that utilize many objects.

## Why should we care about this pattern?

The easiest way to put it: _Because it's powerful._

What makes the composite design pattern so powerful is its ability to treat an object as a composite object. This is possible because they all share a common interface.

What this means is that you can reuse objects without worrying about incompatibility with others.

When you're developing an application and you come across a situation where your dealing with objects that have a tree structure, it could end up being a very good decision to adopt this pattern into your code.

## Examples

Lets say we are building an application for a new business where its main purpose is to help doctors qualify for telemedicine platforms. They do this by collecting their signatures for mandatory documents that are required by law.

We're going to have a `Document` class that will have a `signature` property with a default value of `false`. If the doctor signs the document, `signature` should flip its value to their signature. We're also defining a `sign` method onto it to help make this functionality happen.

This is how the `Document` will look like:

```js
class Document {
  constructor(title) {
    this.title = title
    this.signature = null
  }
  sign(signature) {
    this.signature = signature
  }
}
```

Now when we implement the composite pattern we're going to support similar methods that a `Document` has defined.

```js
class DocumentComposite {
  constructor(title) {
    this.items = []
    if (title) {
      this.items.push(new Document(title))
    }
  }

  add(item) {
    this.items.push(item)
  }

  sign(signature) {
    this.items.forEach((doc) => {
      doc.sign(signature)
    })
  }
}
```

Now here comes the beauty of the pattern. Pay attention to our two most recent code snippets. Let's see this in a visual perspective:

![composite pattern document 1](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/composite+document+composite+1.jpg)

Great! It seems like we are on the right track. We know this because what we have resembles the diagram we had before:

![composite pattern document 2](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/composite+document+composite+2.jpg)

So our tree structure contains 2 leafs/nodes, the `Document` and the `DocumentComposite`. They both share the same interface so they both act as _"parts"_ of the _whole composite tree_.

The thing here is that a leaf/node of the tree that is _not_ a composite (the `Document`) is _not_ a collection or group of objects, so it will stop there. However, a leaf/node that _is_ a composite holds a collection of parts (in our case, the `items`). And remember, the `Document` and `DocumentComposite` shares an interface, sharing the `sign` method.

So where's the power in this? Well, even though the `DocumentComposite` shares the same interface because it has a `sign` method just like the `Document` does, it is actually implementing a more robust approach while still maintaining the end goal.

So instead of this:

```js
const pr2Form = new Document(
  'Primary Treating Physicians Progress Report (PR2)',
)
const w2Form = new Document('Internal Revenue Service Tax Form (W2)')

const forms = []
forms.push(pr2Form)
forms.push(w2Form)

forms.forEach((form) => {
  form.sign('Bobby Lopez')
})
```

We can change our code to make it more robust taking advantage of the composite:

```js
const forms = new DocumentComposite()
const pr2Form = new Document(
  'Primary Treating Physicians Progress Report (PR2)',
)
const w2Form = new Document('Internal Revenue Service Tax Form (W2)')
forms.add(pr2Form)
forms.add(w2Form)

forms.sign('Bobby Lopez')

console.log(forms)
```

In the composite approach, we only need to `sign` once after we added the documents we needed, and it signs all of the documents.

We can confirm this by looking at the result of `console.log(forms)`:

![composite pattern document 3](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/composite+document+composite+3.jpg)

In the example prior to this, we had to manually add the items to an array, loop through each document ourselves and `sign` them.

Let's also not forget the fact that our `DocumentComposite` can hold a collection of items.

So when we did this:

```js
forms.add(pr2Form) // Document
forms.add(w2Form) // Document
```

Our diagram turned into this:

![composite pattern document 4](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/composite+document+composite+4.jpg)

This closely resembles our original diagram as we added the 2 forms:

![composite pattern document 5](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/composite+document+composite+5.jpg)

However, our tree stops because the last leaf of the tree rendered 2 leafs only, which isn't exactly the same as this last screenshot. If we instead made `w2form` a composite instead like this:

```js
const forms = new DocumentComposite()
const pr2Form = new Document(
  'Primary Treating Physicians Progress Report (PR2)',
)
const w2Form = new DocumentComposite('Internal Revenue Service Tax Form (W2)')
forms.add(pr2Form)
forms.add(w2Form)

forms.sign('Bobby Lopez')

console.log(forms)
```

_Then_ our tree can continue to grow:

![composite document composite 7](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/composite+document+composite+7.jpg)

And in the end, we still achieved the same goal where we needed our mandatory documents to be signed:

![end result composite design pattern](https://jsmanifest.s3-us-west-1.amazonaws.com/posts/power-of-the-composite-pattern-in-javascript/end+result+composite+design+pattern.jpg)

And that, is the power of the composite pattern.

## Conclusion

And that concludes the end of this post! I hope you found this to be valuable and look out for more in the future!

Find me on [medium](https://medium.com/@jsmanifest)