Hierarchical Composition with Composite
The Composite pattern is designed to let you compose objects into tree structures to represent part-whole hierarchies. This is especially useful when you want to treat individual objects and compositions of objects uniformly. Common scenarios include representing directories and files in a file system, graphical scene graphs, or organizational charts. By using the Composite pattern, you can build structures where both simple and complex elements conform to the same interface, allowing you to process them in a consistent way.
main.cpp
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677#include <iostream> #include <vector> #include <memory> #include <string> // Base Component class FileSystemEntity { public: virtual ~FileSystemEntity() = default; virtual void display(int indent = 0) const = 0; virtual size_t getSize() const = 0; }; // Leaf class File : public FileSystemEntity { std::string name_; size_t size_; public: File(const std::string& name, size_t size) : name_(name), size_(size) {} void display(int indent = 0) const override { std::cout << std::string(indent, ' ') << "- " << name_ << " (" << size_ << " bytes)" << std::endl; } size_t getSize() const override { return size_; } }; // Composite class Directory : public FileSystemEntity { std::string name_; std::vector<std::shared_ptr<FileSystemEntity>> children_; public: Directory(const std::string& name) : name_(name) {} void add(const std::shared_ptr<FileSystemEntity>& entity) { children_.push_back(entity); } void display(int indent = 0) const override { std::cout << std::string(indent, ' ') << "+ " << name_ << "/" << std::endl; for (const auto& child : children_) child->display(indent + 2); } size_t getSize() const override { size_t total = 0; for (const auto& child : children_) total += child->getSize(); return total; } }; int main() { auto root = std::make_shared<Directory>("root"); auto home = std::make_shared<Directory>("home"); auto user = std::make_shared<Directory>("user"); auto file1 = std::make_shared<File>("file1.txt", 1200); auto file2 = std::make_shared<File>("file2.txt", 800); auto file3 = std::make_shared<File>("notes.md", 500); user->add(file1); user->add(file2); home->add(user); root->add(home); root->add(file3); root->display(); std::cout << "Total size: " << root->getSize() << " bytes" << std::endl; }
Using the Composite pattern greatly simplifies client code that needs to work with tree-like structures. Instead of writing separate logic for handling files and directories, you interact with the base FileSystemEntity interface. Whether you traverse a single file or an entire directory tree, the same methods—such as display and getSize—can be called. This uniformity makes it easy to extend the hierarchy, add new types of components, or process the structure recursively without changing client code.
Bedankt voor je feedback!
Vraag AI
Vraag AI
Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.
Awesome!
Completion rate improved to 10
Hierarchical Composition with Composite
Veeg om het menu te tonen
The Composite pattern is designed to let you compose objects into tree structures to represent part-whole hierarchies. This is especially useful when you want to treat individual objects and compositions of objects uniformly. Common scenarios include representing directories and files in a file system, graphical scene graphs, or organizational charts. By using the Composite pattern, you can build structures where both simple and complex elements conform to the same interface, allowing you to process them in a consistent way.
main.cpp
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677#include <iostream> #include <vector> #include <memory> #include <string> // Base Component class FileSystemEntity { public: virtual ~FileSystemEntity() = default; virtual void display(int indent = 0) const = 0; virtual size_t getSize() const = 0; }; // Leaf class File : public FileSystemEntity { std::string name_; size_t size_; public: File(const std::string& name, size_t size) : name_(name), size_(size) {} void display(int indent = 0) const override { std::cout << std::string(indent, ' ') << "- " << name_ << " (" << size_ << " bytes)" << std::endl; } size_t getSize() const override { return size_; } }; // Composite class Directory : public FileSystemEntity { std::string name_; std::vector<std::shared_ptr<FileSystemEntity>> children_; public: Directory(const std::string& name) : name_(name) {} void add(const std::shared_ptr<FileSystemEntity>& entity) { children_.push_back(entity); } void display(int indent = 0) const override { std::cout << std::string(indent, ' ') << "+ " << name_ << "/" << std::endl; for (const auto& child : children_) child->display(indent + 2); } size_t getSize() const override { size_t total = 0; for (const auto& child : children_) total += child->getSize(); return total; } }; int main() { auto root = std::make_shared<Directory>("root"); auto home = std::make_shared<Directory>("home"); auto user = std::make_shared<Directory>("user"); auto file1 = std::make_shared<File>("file1.txt", 1200); auto file2 = std::make_shared<File>("file2.txt", 800); auto file3 = std::make_shared<File>("notes.md", 500); user->add(file1); user->add(file2); home->add(user); root->add(home); root->add(file3); root->display(); std::cout << "Total size: " << root->getSize() << " bytes" << std::endl; }
Using the Composite pattern greatly simplifies client code that needs to work with tree-like structures. Instead of writing separate logic for handling files and directories, you interact with the base FileSystemEntity interface. Whether you traverse a single file or an entire directory tree, the same methods—such as display and getSize—can be called. This uniformity makes it easy to extend the hierarchy, add new types of components, or process the structure recursively without changing client code.
Bedankt voor je feedback!