Composite Pattern | Structural Design Pattern

Composite Pattern

 The Composite Pattern is a structural design pattern that allows you to compose objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions of objects uniformly. In other words, you can use the same operations on both individual objects and composite objects.

a "partial-whole hierarchy" refers to a structure where individual objects (leaves) and composed objects (composites) share a common interface, allowing them to be treated uniformly.

"uniformly" means that both individual objects (leaves) and composite objects share a common interface. This common interface allows clients to treat them the same way, without needing to distinguish between them.



Key components of the Composite Pattern include:

Component: Declares the interface for objects in the composition. It can be an abstract class or interface with operations that are common to both leaf and composite elements.

Leaf: Represents individual objects in the composition. These are the "building blocks" with no children.

Composite: Represents a group of components as a single component. It can contain leaves or other composites, enabling the creation of complex structures.

Example in C#:



_______

using System;
using System.Collections.Generic;

// Component interface
public interface IComponent
{
    void Display();
}

// Leaf class
public class Leaf : IComponent
{
    private readonly string _name;

    public Leaf(string name)
    {
        _name = name;
    }

    public void Display()
    {
        Console.WriteLine($"Leaf: {_name}");
    }
}

// Composite class
public class Composite : IComponent
{
    private readonly List<IComponent> _children = new List<IComponent>();

    public void Add(IComponent component)
    {
        _children.Add(component);
    }

    public void Display()
    {
        foreach (var child in _children)
        {
            child.Display();
        }
    }
}

class Program
{
    static void Main()
    {
        // Creating leaf objects
        IComponent leaf1 = new Leaf("Leaf 1");
        IComponent leaf2 = new Leaf("Leaf 2");
        IComponent leaf3 = new Leaf("Leaf 3");

        // Creating a composite object and adding leaves
        Composite composite = new Composite();
        composite.Add(leaf1);
        composite.Add(leaf2);

        // Creating another composite object and adding a leaf
        Composite composite2 = new Composite();
        composite2.Add(leaf3);

        // Adding the second composite to the first
        composite.Add(composite2);

        // Displaying the structure
        Console.WriteLine("Composite Structure:");
        composite.Display();
    }
}
_______


In this example:
Leaf represents individual elements.

Composite represents a group of elements, including leaves and other composites.

The Display method is uniform across both leaf and composite objects, allowing you to treat them uniformly.

 The pattern is particularly useful when dealing with tree-like structures, such as graphic systems, file systems, or organizational hierarchies.







Visualizing the Composite Pattern is often done using a tree structure, as it naturally represents part-whole hierarchies. Here's a simple way to visualize it:

Consider a graphical system where you have shapes:

Leaf Nodes (Individual Objects):
A circle
A rectangle

Composite Nodes (Composed Objects):
A group of circles
A group of rectangles
A combination of circles and rectangles


This could be represented as a tree:- Composite (Combination of circles and rectangles)
  - Leaf (Circle)
  - Leaf (Circle)
  - Leaf (Rectangle)
  - Composite (Group of rectangles)
    - Leaf (Rectangle)
    - Leaf (Rectangle)

In this representation:

Composite Nodes represent groups or combinations.

Leaf Nodes represent individual elements.

Example

______

// Component interface
public interface IComponent
{
    void Display();
}

// Leaf class
public class Leaf : IComponent
{
    private readonly string _name;

    public Leaf(string name)
    {
        _name = name;
    }

    public void Display()
    {
        Console.WriteLine($"Leaf: {_name}");
    }
}

// Composite class
public class Composite : IComponent
{
    private readonly List<IComponent> _children = new List<IComponent>();

    public void Add(IComponent component)
    {
        _children.Add(component);
    }

    public void Display()
    {
        foreach (var child in _children)
        {
            child.Display();
        }
    }
}

class Program
{
    static void Main()
    {
        // Creating leaf objects
        IComponent circle = new Leaf("Circle");
        IComponent rectangle = new Leaf("Rectangle");

        // Creating composite objects and adding leaves
        Composite combination = new Composite();
        combination.Add(circle);
        combination.Add(rectangle);

        Composite groupOfRectangles = new Composite();
        groupOfRectangles.Add(new Leaf("Rectangle"));
        groupOfRectangles.Add(new Leaf("Rectangle"));

        // Creating another composite object and adding leaves and a composite
        Composite composite = new Composite();
        composite.Add(combination);
        composite.Add(groupOfRectangles);

        // Displaying the structure
        Console.WriteLine("Composite Structure:");
        composite.Display();
    }
}
______

In this example, we can see how leaves (individual objects) and composites (groups or combinations) can be organized into a hierarchical structure. The Display method is invoked uniformly on both leaves and composites.



File system example

 Leaf Nodes (Individual Objects):File (representing individual files)

Composite Nodes (Composed Objects):Folder (representing a directory that can contain files and subfolders)


- Composite (Root Folder)
  - Leaf (File: Document.txt)
  - Composite (Folder: Images)
    - Leaf (File: Image1.jpg)
    - Leaf (File: Image2.png)
  - Composite (Folder: Videos)
    - Composite (Folder: Family)
      - Leaf (File: Vacation.mp4)
    - Leaf (File: Tutorial.mp4)




______
using System;
using System.Collections.Generic;

// Component interface
public interface IFileSystemComponent
{
    void Display();
}

// Leaf class
public class File : IFileSystemComponent
{
    private readonly string _name;

    public File(string name)
    {
        _name = name;
    }

    public void Display()
    {
        Console.WriteLine($"File: {_name}");
    }
}

// Composite class
public class Folder : IFileSystemComponent
{
    private readonly string _name;
    private readonly List<IFileSystemComponent> _children = new List<IFileSystemComponent>();

    public Folder(string name)
    {
        _name = name;
    }

    public void Add(IFileSystemComponent component)
    {
        _children.Add(component);
    }

    public void Display()
    {
        Console.WriteLine($"Composite (Folder): {_name}");
        foreach (var child in _children)
        {
            child.Display();
        }
    }
}

class Program
{
    static void Main()
    {
        // Creating leaf objects (files)
        IFileSystemComponent document = new File("Document.txt");
        IFileSystemComponent image1 = new File("Image1.jpg");
        IFileSystemComponent image2 = new File("Image2.png");
        IFileSystemComponent vacationVideo = new File("Vacation.mp4");
        IFileSystemComponent tutorialVideo = new File("Tutorial.mp4");

        // Creating composite objects (folders) and adding leaves (files)
        Folder rootFolder = new Folder("Root Folder");
        rootFolder.Add(document);

        Folder imagesFolder = new Folder("Images");
        imagesFolder.Add(image1);
        imagesFolder.Add(image2);
        rootFolder.Add(imagesFolder);

        Folder videosFolder = new Folder("Videos");
        videosFolder.Add(new Folder("Family")).Add(vacationVideo);
        videosFolder.Add(tutorialVideo);
        rootFolder.Add(videosFolder);

        // Displaying the file system structure
        Console.WriteLine("File System Structure:");
        rootFolder.Display();
    }
}
______


In this example, the File class represents individual files, and the Folder class represents folders that can contain files or other folders. The Display method is invoked uniformly on both files and folders, showcasing the Composite Pattern in a file system context.

Comments