Open In App

Composite Design Pattern | JavaScript Design Patterns

The Composite Design pattern is a way of organizing objects. It helps us handle different objects in a similar way when they are put together to create a structure with parts and wholes. These parts and wholes are like building blocks that can be split into smaller pieces and then put together to make a tree-like structure.

The composite design pattern allows us to build structures so that clients can work with both individual elements and collections of elements seamlessly and consistently and makes it easy to add new types of components (individual or composite) without modifying the client code promoting flexibility and reusability.



Components of the Composite Design Pattern

The components of the Composite Design Pattern include:

Note: JavaScript doesn’t support Interfaces directly. An alterative could be create a class and modify accordingly.



Implementation of the Composite Design Pattern in JavaScript

Let us follow the below steps to implement a ‘File System’ using Composite Design Pattern.

Step 1: Create a Component class




class Component {
  print() {
    throw new Error('Override this method');
  }
 
  size() {
    throw new Error('Override this method');
  }
}

Explanation:

This class `Component` represents the class that declares the method definitions that can be provided with accurate implementations. In this Component class, I declared two methods namely `print` and `size` whose implementation is hidden and will be override by subclasses. These methods are assumed to be commonly shared with each individual part in the whole hierarchy.

Step 2: Create the Leaf class




class File extends Component {
  constructor(name, size, location) {
    super();
    this.name = name;
    this.size = size;
    this.location = location
  }
 
  print() {
    console.log(`The File with the name ${this.name} whose size is ${this.size} KB, present is ${this.location}`);
  }
 
  size() {
    return this.size;
  }
}

Explanation:

I have created the `File` class which represent individual component in the File System. This class extends the `Component` class and initializes a constructor with three parameters namely `name`, `size`, `location`. The methods `print` and `size` are overrided and accurately defined in this File class. The purpose of print method is to print the details of name, size and location of the file and the purpose of the size function is to return the size of the file.

Step 3: Create the Composite class




class Folder extends Component {
  constructor(name) {
    super();
    this.name = name;
    this.files= [];
  }
 
  add(file) {
    this.files.push(file);
  }
 
  delete(file) {
    const idx = this.children.indexOf(file);
    if (index !== -1) {
      this.files.splice(idx, 1);
    }
  }
 
  print() {
    console.log(`Folder: ${this.name}`);
    this.files.forEach((file) => {
      file.print();
    });
  }
}

Explanation:

The Folder class represents the `Composite` class whose purpose is to hold the leaf classes and define methods to `add`, `delete` and manipulate the hierarchy. I have defined constructor which initializes the name of the folder/directory and an array to hold the files of that folder. Followed by that, I have defined two methods names `add` and `delete` whose purpose is to add the file to the part-whole hierarchy and delete the file from the hierarchy respectively. The method `print` is also overrided to provide the specific implementation for the folder.

Step 4: Instance creation and usage




const file = new File('document.txt', 10, 'c:/users/downloads');
const folder = new Folder('users');
folder.add(file);
 
const root = new Folder('Root');
root.add(folder);
 
console.log('File system structure:');
root.print();

Output:

output

Explanation:

In this step, I am creating instance for the File class as file along with the values of name, size and location. I have created a instance for the Folder class with the name ‘users’ and added the file to the folder using the add method. I have also created a instance called root which represents the root directory of the filesystem which holds all the directories of the system and finally used print method to display the overall File system structure.

Below is the diagram for the above example:

Advantages of the Composite Design Pattern in JavaScript Design Pattern

Disadvantages of the Composite Design Pattern in JavaScript Design Pattern


Article Tags :