Introduction to the Composite Pattern

Introduction to the Composite Pattern

Welcome back! You have learned about the Adapter Pattern and how it helps make incompatible interfaces work together seamlessly. Now, let's dive into another crucial structural pattern that focuses on composition: the Composite Pattern.

The Composite Pattern allows you to build complex structures by combining objects into tree-like structures to represent part-whole hierarchies. This pattern is particularly useful when dealing with applications like file systems, GUI frameworks, or organizational structures where you need to treat individual objects and compositions of objects uniformly.

What You'll Learn

In this lesson, we will explore how to implement the Composite Pattern in C++. We will focus on an organizational structure scenario. You will learn how to create and manage employees, both individual developers, and groups of developers managed by a manager. Here's a snippet from the code you'll be working with:

We will start by creating an abstract Employee class with a showDetails method to serve as an interface:

#include <iostream>
#include <vector>
#include <algorithm>

class Employee {
public:
    virtual void showDetails() = 0;
    virtual ~Employee() = default;
};

Next, we will create a Developer class that inherits from the Employee class. The Developer class will have a showDetails method that prints the developer's name and position:

class Developer : public Employee {
public:
    Developer(const std::string& name, const std::string& position)
        : name(name), position(position) {}

    void showDetails() override {
        std::cout << name << " works as " << position << "." << std::endl;
    }

private:
    std::string name;
    std::string position;
};

Finally, we will create a Manager class that inherits from the Employee class. The Manager class will have a vector of Employee pointers to manage multiple employees. It will also have methods to add, remove, and display employee details:


class Manager : public Employee {
public:
    ~Manager() {
        for (auto employee : employees) {
            delete employee;
        }
    }

    void add(Employee* employee) {
        employees.push_back(employee);
    }

    void remove(Employee* employee) {
        employees.erase(std::remove(employees.begin(), employees.end(), employee), employees.end());
    }

    void showDetails() override {
        for (auto employee : employees) {
            employee->showDetails();
        }
    }

private:
    std::vector<Employee*> employees;
};

Notice how Manager can contain multiple Employee objects, allowing you to build a composite structure. Note, that the employees vector can even contain other Manager objects, creating a nested hierarchy.

Now let's see how you can use the Composite Pattern to manage employees in an organization:

int main() {
    Employee* dev1 = new Developer("Alice", "Software Engineer");
    Employee* dev2 = new Developer("Bob", "Frontend Developer");

    Employee* manager = new Manager();
    manager->add(dev1);
    manager->add(dev2);

    manager->showDetails(); // Output: Alice works as Software Engineer. Bob works as Frontend Developer.

    delete manager; // Manager destructor will delete dev1 and dev2
}

In this example, Employee is an abstract class with a showDetails method, which is implemented by both Developer and Manager classes. The Manager class can contain multiple employees, allowing you to build a composite structure.

Let's understand the key components of the Composite Pattern:

  • Component: An abstract class that defines the interface for all objects in the composition. In our example, Employee is the component class.
  • Leaf: A concrete class that represents individual objects in the composition. In our example, Developer is the leaf class.
  • Composite: A concrete class that represents compositions of objects. In our example, Manager is the composite class.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal