Mastering the Composite Design Pattern: Unifying Files and Folders in Your Application

In software engineering, managing hierarchical structures such as files and folders efficiently is a common challenge. The Composite design pattern provides a powerful solution for such use cases.

Mentor

Blog

Composite Design Pattern:

Composite pattern is used where we need to treat a group of objects in similar way as a single object. Composite pattern composes objects in term of a tree structure to represent part as well as whole hierarchy. This type of design pattern comes under structural pattern as this pattern creates a tree structure of group of objects.

Components:

The Composite design pattern consists of several main components, each playing a specific role in organising and interacting with hierarchical structures. Here are the key components:

Component:

This is the interface or abstract class that declares the common interface for all objects in the composition. It defines operations that are common to both composite and leaf nodes.

1- Component:

This is the interface or abstract class that declares the common interface for all objects in the composition. Also It defines operations that are common to both composite and leaf nodes.

2- Leaf:

The Leaf represents the end objects in a composition, i.e., objects that do not have any children.

3- Composite:

The Composite class represents the complex objects that may have children. Also It maintains a collection of child components, which can be either leaf nodes or other composite nodes. And It delegates requests to its child components recursively.

4- Client:

The Client is responsible for interacting with the components of the composite structure.

Building a File System with the Composite Design Pattern

// Component interface
public interface FileSystemComponent {
    String getName();
    int getSize();
    void ls();
}


// Leaf component representing a file public class File implements FileSystemComponent { private String name; private int size; public File(String name, int size) { this.name = name; this.size = size; } @Override public String getName() { return name; } @Override public int getSize() { return size; } @Override public void ls() { System.out.println(getName() + " (" + getSize() + " KB)"); } }


import java.util.ArrayList; import java.util.List; // Composite component representing a folder public class Folder implements FileSystemComponent { private String name; private List<FileSystemComponent> components; public Folder(String name) { this.name = name; this.components = new ArrayList<>(); } @Override public String getName() { return name; } @Override public int getSize() { int totalSize = 0; for (FileSystemComponent component : components) { totalSize += component.getSize(); } return totalSize; } @Override public void ls() { System.out.println(getName() + " (" + getSize() + " KB)"); for (FileSystemComponent component : components) { component.ls(); } } public void addComponent(FileSystemComponent component) { components.add(component); } public void removeComponent(FileSystemComponent component) { components.remove(component); } }


public class Main { public static void main(String[] args) { // Create files FileSystemComponent file1 = new File("file1.txt", 10); // Size in KB FileSystemComponent file2 = new File("file2.txt", 20); // Create folders Folder folder1 = new Folder("folder1"); Folder folder2 = new Folder("folder2"); // Add files to folders folder1.addComponent(file1); folder2.addComponent(file2); // Add folders to folders Folder root = new Folder("root"); root.addComponent(folder1); root.addComponent(folder2); // List contents of root folder root.ls(); } }


For more such amazing content on LLD you can book 1:1 session with me where we can discuss things at length.