Going over the Composite Design Pattern in JavaScript

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.

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 intention of a composite is to compose multiple objects into a certain tree structure. This tree structure represents a part-whole hierarchy.

To understand the composite pattern in greater detail, we’d have to understand what a part-whole is and what it would look like from 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 leaves/nodes) is also a leaf or node.

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

Now that we have a clearer understanding of the part-whole concept, let’s go back to the term composite. We said that the intention of a composite is to compose any of these objects (leaves/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 Uses the Pattern?

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

The files (we can refer to anything inside a directory as an “item” at this point, which makes more sense) are the leaves/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 on 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 it 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 you’re 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

Let’s 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 what the Document will look like:

Document.ts

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 defined.

DocumentComposite.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 from a visual perspective:

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

So, our tree structure contains two leaves/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 share 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:

forms.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:

forms.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):

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:

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

Our diagram turned into this:

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

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

forms.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:

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

And that is the power of the composite pattern.

Conclusion

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

Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

What’s new in HTML6

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

Programming a Javascript Simon Game Tutorial

Programming a Javascript Simon Game Tutorial

In this javascript tutorial, I recorded myself live programming an html5 javascript simon game.

In this javascript tutorial, I recorded myself live programming an html5 javascript simon game.

For those who don't know, I'm a full stack web developer who has been in the industry for over 5 years now. There is a lot of things I have learned along the way and I'd like to share that knowledge with anyone wanting to learn!

like this video if you found it useful and would like to see more videos of the same content.

subscribe to my channel if you are trying to improve your abilities as a web developer, software engineer, or even if you are just learning to code.

Don't forget to turn on those bell notifications!

Understanding Memoization And Dynamic Programming in Javascript

Understanding Memoization And Dynamic Programming in Javascript

In this Javascript tutorial I will explain what memoization is, how to use it, when you should use memoization, how to use memoization, what dynamic programming is, how to use memoization in dynamic programming. Memoization is a big complicated word that you may have never even heard before, but you may be surprised to know that you are most likely already using memoization without even realizing it.

Memoization is a big complicated word that you may have never even heard before, but you may be surprised to know that you are most likely already using memoization without even realizing it. Memoization is just the act of caching values so that they can be calculated quicker in the future. Memoization is really useful in all parts of programming, but where it is most useful is in dynamic programming. In this video I will explain what memoization is, how to use it, and why it is so useful especially in dynamic programming.

🧠 Concepts Covered:

  • What memoization is
  • When you should use memoization
  • How to use memoization
  • What dynamic programming is
  • How to use memoization in dynamic programming

JavaScript Programming Tutorial - Full JavaScript Course for Beginners

JavaScript Programming Tutorial - Full JavaScript Course for Beginners

JavaScript is the programming language of HTML and the Web. JavaScript is easy to learn. This tutorial will teach you JavaScript from basic to advanced. JavaScript Programming Tutorial - Full JavaScript Course for Beginners

Watch this JavaScript tutorial for beginners to learn JavaScript programming from scratch. 👍

⭐️Course Contents⭐️

01 | Introduction

Get an introduction from Bob, as he kicks off the course, sets expectations, and gives you a little guidance for the road ahead.

02 | Setting Up the Development Environment

See how to install Node and Visual Studio Code, and learn why you need each. Watch as Bob writes a first tiny line of code to make sure that the installation is ready.

03 | Basic JavaScript Syntax

Hear about the basics of the JavaScript syntax, including how JavaScript is executed, how to create a properly formed statement, and more.

04 | Variables

Learn what variables are and how to declare, initialize, set, and get values from them.

05 | Data Types

JavaScript works with data types differently than other programming languages do. Learn from Bob as he explains some of the most basic data types and how to determine the type held by a variable.

06 | Type Coercion and Conversion

Sometimes you need to explicitly convert the data type of a value into a different data type. Sometimes JavaScript will do this automatically for you. Bob explains how and why this happens.

07 | Expressions and Operators

Learn how to spot a well-formed expression and how to compose expressions through the combination of operators and operands.

08 | Arrays

Watch as Bob demonstrates how to use arrays, how to add/remove elements of an array, how to access elements of an array using the index, how to get the number of elements in an array, and more.

09 | Function Declaration

Get an introduction to functions, as Bob shows you one way to define a function, how to call the function, how to pass parameters into a function, how to return values from a function, and more.

10 | Function Expressions

Sometimes a function declaration is more than you need. Get details in this lesson, as Bob demonstrates how to use a function expression and how to create an immediately invoked function expression.

11 | Decision Statements

Learn how to add logic to your applications by testing conditions using if / else statements, switch / case statements, and the ternary operator.

12 | Iteration Statements

Watch as Bob introduces the For and While statements, which enable you to loop through lists of values and perform operations on them.

13 | Basics of Scope

Hear an explanation of the notion of the lifetime of variables and their reach into other code blocks, in this discussion of scope.

14 | Returning Functions from Functions

As a building block toward a more sophisticated approach to building JavaScript applications, see how you can return functions from functions.

15 | Object Literals

Objects contain properties and functions that describe attributes of the object and its behavior, respectively. Watch as Bob demonstrates how to create object literals.

16 | Module Pattern and Revealing Module Pattern

Learn how to introduce variables and functions without leaving an unnecessarily large footprint on the global scope.

17 | Closures

Closures allow developers to bind functions to their execution context, including variables, so you can build specialized versions of functions. Learn how closures work and how to create them.

18 | this Keyword

Get the details on the "this" keyword, which causes a lot of confusion for JavaScript developers. Listen as Bob explains what this mysterious object is and how to bend it to your will.

19 | Destructuring

See how to use destructuring, a new feature in JavaScript that allows you to unpack array elements or object properties in a concise syntax.

20 | String Template Literals

Learn about the new string template literal syntax to enable string interpolation, multi-line string formatting, and more.

21 | Regular Expressions

Working with string data, Bob explains how use regular expressions to determine such things as whether a string matches a specific pattern or whether an instance of the pattern exists in a string.

22 | Built-In Natives

Join Bob as he examines native, built-in JavaScript functions that return objects that box the primitive types in order to provide additional helper methods on your values.

23 | Constructor Function Calls with the new Keyword

Learn how constructor functions work, see how to make key distinctions in what they are, and find out why they’re helpful.

24 | Objects and the Prototype Chain

Moving past the absolute beginner matter, listen in as Bob explains how objects work in JavaScript and how you can create an object that is linked to another object.

25 | JavaScript Classes

Bob demonstrates how “syntactic sugar” works on top of the existing functions and prototype chaining to help JavaScript resemble more traditional object-oriented programming languages.

26 | Arrow Functions

The latest version of JavaScript added arrow functions, a shorthand syntax for creating functions. Watch as Bob demonstrates how to create them and shows where they’re useful.

27 | Truthy and Falsy Values

Listen is as Bob circles back to topics that are important (but didn’t easily fit into earlier topics) and looks at the odd way in which JavaScript evaluates certain expressions as truthy and falsy.

28 | null Type

Similar to the undefined primitive type, the null type represents a variable that has no reference to an object when one was expected. Hear an explanation of how and why we should think about nulls.

29 | Date Objects

No discussion of JavaScript would be complete without understanding the Date built-in native function which provides properties and methods for working with dates and times.

30 | String Methods

The built-in native String function provides several very useful methods for manipulating and evaluating strings. Watch Bob demonstrate how to use a few of the most useful ones.

31 | Array Methods

We’ve worked with arrays throughout this course. Now Bob takes a few minutes to show you some of the most useful methods provided by the Array built-in native function.

32 | Error Handling with Try Catch

See how to wrap a try/catch/finally statement around potentially problematic code to anticipate everything that could go wrong with it, and learn other error-handling tips.

33 | Understanding the Document Object Model

Watch Bob examine the web browser environment and how it creates an object graph of nodes that represent elements, their attributes, and text, plus how to properly attach your code to an HTML page.

34 | Working with DOM Nodes

Continuing from the previous video, Bob demonstrates a slightly more compelling example that helps us understand how to manipulate, create, and delete element nodes and attribute nodes.

35 | Course Conclusion

In this final video, Bob briefly adds some closing comments and well wishes. You can also optionally complete a survey to provide insight into how Microsoft can improve this course.

Thanks for watching

If you liked this post, please do share/like it with all of your programming buddies!

Follow us on Facebook | Twitter