CODESAMPLE

Composite - C++

Share on:

The Composite pattern treats individual objects and compositions of objects uniformly. It defines hierarchical elements (components) to represent whole-part relationships. The client can interact with these components consistently without knowing whether it’s dealing with a simple element or a complex composition. This example represents a graphical shapes hierarchy where shapes can be composed of other shapes. We define an abstract Shape class, concrete Circle and Square classes implementing the leaf nodes, and a ShapeGroup class representing a composite node. The operation() method (here, area()) is defined in the abstract class and implemented in all concrete classes, enabling uniform interaction with both primitive shapes and groups. This leverages C++’s polymorphism and class hierarchy for a natural and efficient composite structure.

#include <iostream>
#include <vector>
#include <cmath>

// Component
class Shape {
public:
  virtual double area() = 0;
  virtual ~Shape() = default;
};

// Leaf
class Circle : public Shape {
private:
  double radius_;
public:
  Circle(double radius) : radius_(radius) {}
  double area() override { return M_PI * radius_ * radius_; }
};

// Leaf
class Square : public Shape {
private:
  double side_;
public:
  Square(double side) : side_(side) {}

  double area() override { return side_ * side_; }
};

// Composite
class ShapeGroup : public Shape {
private:
  std::vector<Shape*> shapes_;
public:
  void add(Shape* shape) { shapes_.push_back(shape); }
  void remove(Shape* shape) {
    for (size_t i = 0; i < shapes_.size(); ++i) {
      if (shapes_[i] == shape) {
        shapes_.erase(shapes_.begin() + i);
        return;
      }
    }
  }

  double area() override {
    double total_area = 0.0;
    for (Shape* shape : shapes_) {
      total_area += shape->area();
    }
    return total_area;
  }

  ~ShapeGroup() {
    for (Shape* shape : shapes_) {
      delete shape;
    }
  }
};

int main() {
  Shape* circle = new Circle(5.0);
  Shape* square = new Square(4.0);

  ShapeGroup* group = new ShapeGroup();
  group->add(circle);
  group->add(square);

  Shape* another_circle = new Circle(2.0);
  group->add(another_circle);

  std::cout << "Total area: " << group->area() << std::endl;

  delete group; // ShapeGroup destructor deletes contained shapes

  return 0;
}