当前位置: 首页 > news >正文

第八章:组合模式 - 整体部分的统一大师

第八章:组合模式 - 整体部分的统一大师

故事延续:层次结构的统一之道

在Bridge展示完他的桥梁构建之道后,Composite身形奇特地走出,他时而是一个完整的巨人,时而又散开成一群小兵,但无论合体还是分散,行动都整齐划一。这位高手的声音瓮声瓮气,却带着一种奇特的韵律感。

"Bridge兄的抽象实现分离确实精妙,"Composite说道,“但在处理层次结构时,需要更加统一的处理方式。我的武学核心在于——将对象组合成树形结构以表示’部分-整体’的层次结构,使得用户对单个对象和组合对象的使用具有一致性。”

组合模式的武学精要

核心心法

Composite的身体时而聚合时而分散,展示着整体与部分的统一:“我的十六字真言是——整体部分一致,树形结构统一。通过让单个对象和组合对象实现相同的接口,我可以让客户端无差别地处理简单元素和复杂元素。”

C++ 代码实战
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>// 组件接口:文件系统条目
class FileSystemComponent {
public:virtual ~FileSystemComponent() = default;// 公共接口 - 单个对象和组合对象都要实现virtual std::string getName() const = 0;virtual long getSize() const = 0;virtual void display(int depth = 0) const = 0;virtual std::string getType() const = 0;// 组合对象特有的方法 - 在基类中提供默认实现virtual void addComponent(std::shared_ptr<FileSystemComponent> component) {throw std::runtime_error("不支持添加操作: " + getName());}virtual void removeComponent(std::shared_ptr<FileSystemComponent> component) {throw std::runtime_error("不支持删除操作: " + getName());}virtual std::vector<std::shared_ptr<FileSystemComponent>> getChildren() const {return {};}virtual bool isComposite() const {return false;}// 工具方法virtual std::string getIndent(int depth) const {return std::string(depth * 2, ' ');}
};// 叶子节点:文件
class File : public FileSystemComponent {
private:std::string name_;long size_;std::string extension_;public:File(const std::string& name, long size, const std::string& extension = ""): name_(name), size_(size), extension_(extension) {}std::string getName() const override {return name_;}long getSize() const override {return size_;}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "📄 " << name_;if (!extension_.empty()) {std::cout << " (" << extension_ << ")";}std::cout << " - " << formatSize(size_) << std::endl;}std::string getType() const override {return "文件";}// 文件特有方法std::string getExtension() const {return extension_;}void rename(const std::string& newName) {std::cout << "✏️ 重命名文件: " << name_ << " -> " << newName << std::endl;name_ = newName;}private:std::string formatSize(long bytes) const {const char* units[] = {"B", "KB", "MB", "GB"};int unitIndex = 0;double size = bytes;while (size >= 1024 && unitIndex < 3) {size /= 1024;unitIndex++;}std::stringstream ss;ss.precision(2);ss << std::fixed << size << " " << units[unitIndex];return ss.str();}
};// 叶子节点:符号链接
class Symlink : public FileSystemComponent {
private:std::string name_;std::shared_ptr<FileSystemComponent> target_;public:Symlink(const std::string& name, std::shared_ptr<FileSystemComponent> target): name_(name), target_(target) {}std::string getName() const override {return name_;}long getSize() const override {return target_->getSize(); // 符号链接的大小通常很小,这里返回目标大小}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "🔗 " << name_ << " -> " << target_->getName() << std::endl;}std::string getType() const override {return "符号链接";}// 符号链接特有方法std::shared_ptr<FileSystemComponent> getTarget() const {return target_;}
};// 组合节点:目录
class Directory : public FileSystemComponent {
private:std::string name_;std::vector<std::shared_ptr<FileSystemComponent>> children_;mutable long cachedSize_ = -1; // 缓存大小,避免重复计算public:Directory(const std::string& name) : name_(name) {}std::string getName() const override {return name_;}long getSize() const override {if (cachedSize_ == -1) {cachedSize_ = 0;for (const auto& child : children_) {cachedSize_ += child->getSize();}}return cachedSize_;}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "📁 " << name_ << "/ - " << formatSize(getSize()) << std::endl;// 递归显示子节点for (const auto& child : children_) {child->display(depth + 1);}}std::string getType() const override {return "目录";}// 组合对象特有方法void addComponent(std::shared_ptr<FileSystemComponent> component) override {children_.push_back(component);cachedSize_ = -1; // 使缓存失效std::cout << "✅ 添加 " << component->getType() << ": " << component->getName() << " 到目录: " << name_ << std::endl;}void removeComponent(std::shared_ptr<FileSystemComponent> component) override {auto it = std::find(children_.begin(), children_.end(), component);if (it != children_.end()) {children_.erase(it);cachedSize_ = -1; // 使缓存失效std::cout << "🗑️ 从目录 " << name_ << " 中移除: " << component->getName() << std::endl;} else {std::cout << "❌ 在目录 " << name_ << " 中未找到: " << component->getName() << std::endl;}}std::vector<std::shared_ptr<FileSystemComponent>> getChildren() const override {return children_;}bool isComposite() const override {return true;}// 目录特有方法int getItemCount() const {return children_.size();}std::shared_ptr<FileSystemComponent> findComponent(const std::string& name) const {for (const auto& child : children_) {if (child->getName() == name) {return child;}// 如果是目录,递归查找if (auto dir = std::dynamic_pointer_cast<Directory>(child)) {auto found = dir->findComponent(name);if (found) return found;}}return nullptr;}void listContents() const {std::cout << "\n📋 目录 " << name_ << " 的内容 (" << getItemCount() << " 个项目):" << std::endl;for (const auto& child : children_) {std::cout << "  " << (child->isComposite() ? "📁" : "📄") << " " << child->getName() << " (" << child->getType() << ")" << std::endl;}}private:std::string formatSize(long bytes) const {const char* units[] = {"B", "KB", "MB", "GB"};int unitIndex = 0;double size = bytes;while (size >= 1024 && unitIndex < 3) {size /= 1024;unitIndex++;}std::stringstream ss;ss.precision(2);ss << std::fixed << size << " " << units[unitIndex];return ss.str();}
};// 组合节点:压缩目录
class CompressedDirectory : public Directory {
private:double compressionRatio_;public:CompressedDirectory(const std::string& name, double compressionRatio = 0.5): Directory(name), compressionRatio_(compressionRatio) {}long getSize() const override {// 压缩目录的大小是原始大小的压缩比率return static_cast<long>(Directory::getSize() * compressionRatio_);}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "🗜️ " << getName() << ".zip/ - " << formatSize(getSize()) << " (压缩率: " << (compressionRatio_ * 100) << "%)" << std::endl;for (const auto& child : getChildren()) {child->display(depth + 1);}}std::string getType() const override {return "压缩目录";}private:std::string formatSize(long bytes) const {const char* units[] = {"B", "KB", "MB", "GB"};int unitIndex = 0;double size = bytes;while (size >= 1024 && unitIndex < 3) {size /= 1024;unitIndex++;}std::stringstream ss;ss.precision(2);ss << std::fixed << size << " " << units[unitIndex];return ss.str();}
};

UML 武功秘籍图

«abstract»
FileSystemComponent
+getName() : string
+getSize() : long
+display(int) : void
+getType() : string
+addComponent(FileSystemComponent) : void
+removeComponent(FileSystemComponent) : void
+getChildren()
+isComposite() : bool
+getIndent(int) : string
File
-string name_
-long size_
-string extension_
+getName() : string
+getSize() : long
+display(int) : void
+getType() : string
+getExtension() : string
+rename(string) : void
Symlink
-string name_
-shared_ptr<FileSystemComponent> target_
+getName() : string
+getSize() : long
+display(int) : void
+getType() : string
+getTarget()
Directory
-string name_
-vector<shared_ptr>FileSystemComponent<> children_
-long cachedSize_
+getName() : string
+getSize() : long
+display(int) : void
+getType() : string
+addComponent(FileSystemComponent) : void
+removeComponent(FileSystemComponent) : void
+getChildren()
+isComposite() : bool
+getItemCount() : int
+findComponent(string)
+listContents() : void
CompressedDirectory
-double compressionRatio_
+getSize() : long
+display(int) : void
+getType() : string

实战演练:组织架构管理系统

#include <map>
#include <algorithm>// 更复杂的组合模式应用:组织架构系统// 组件接口:组织单元
class OrganizationUnit {
public:virtual ~OrganizationUnit() = default;// 公共接口virtual std::string getName() const = 0;virtual std::string getRole() const = 0;virtual double getSalary() const = 0;virtual void display(int depth = 0) const = 0;virtual std::string getType() const = 0;// 组合对象方法virtual void addSubordinate(std::shared_ptr<OrganizationUnit> subordinate) {throw std::runtime_error(getName() + " 不能有下属");}virtual void removeSubordinate(std::shared_ptr<OrganizationUnit> subordinate) {throw std::runtime_error(getName() + " 不能有下属");}virtual std::vector<std::shared_ptr<OrganizationUnit>> getSubordinates() const {return {};}virtual bool isComposite() const {return false;}// 工具方法virtual std::string getIndent(int depth) const {return std::string(depth * 3, ' ');}
};// 叶子节点:普通员工
class Employee : public OrganizationUnit {
private:std::string name_;std::string position_;double salary_;std::string department_;public:Employee(const std::string& name, const std::string& position, double salary, const std::string& department = ""): name_(name), position_(position), salary_(salary), department_(department) {}std::string getName() const override {return name_;}std::string getRole() const override {return position_;}double getSalary() const override {return salary_;}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "👤 " << name_ << " - " << position_;if (!department_.empty()) {std::cout << " (" << department_ << ")";}std::cout << " - ¥" << salary_ << std::endl;}std::string getType() const override {return "员工";}// 员工特有方法void promote(const std::string& newPosition, double newSalary) {std::cout << "⬆️ 晋升 " << name_ << ": " << position_ << " -> " << newPosition << ", 薪资: ¥" << salary_ << " -> ¥" << newSalary << std::endl;position_ = newPosition;salary_ = newSalary;}void transferDepartment(const std::string& newDepartment) {std::cout << "🔄 调动 " << name_ << " 从 " << department_ << " 到 " << newDepartment << std::endl;department_ = newDepartment;}
};// 叶子节点:实习生
class Intern : public Employee {
private:std::string school_;int duration_; // 实习时长(月)public:Intern(const std::string& name, const std::string& school, double salary, int duration, const std::string& department = ""): Employee(name, "实习生", salary, department), school_(school), duration_(duration) {}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "🎓 " << getName() << " - 实习生 (" << school_ << ")" << " - " << duration_ << "个月 - ¥" << getSalary() << std::endl;}std::string getType() const override {return "实习生";}// 实习生特有方法void extendInternship(int additionalMonths) {duration_ += additionalMonths;std::cout << "📅 延长 " << getName() << " 的实习期 " << additionalMonths << " 个月" << std::endl;}
};// 组合节点:经理
class Manager : public OrganizationUnit {
private:std::string name_;std::string position_;double baseSalary_;std::string department_;std::vector<std::shared_ptr<OrganizationUnit>> subordinates_;public:Manager(const std::string& name, const std::string& position, double baseSalary, const std::string& department): name_(name), position_(position), baseSalary_(baseSalary), department_(department) {}std::string getName() const override {return name_;}std::string getRole() const override {return position_;}double getSalary() const override {// 经理薪资 = 基础薪资 + 团队规模奖金double teamBonus = subordinates_.size() * 500;return baseSalary_ + teamBonus;}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "👔 " << name_ << " - " << position_ << " (" << department_ << ")"<< " - ¥" << getSalary() << " (团队: " << subordinates_.size() << "人)" << std::endl;// 显示下属for (const auto& subordinate : subordinates_) {subordinate->display(depth + 1);}}std::string getType() const override {return "经理";}// 组合对象特有方法void addSubordinate(std::shared_ptr<OrganizationUnit> subordinate) override {subordinates_.push_back(subordinate);std::cout << "✅ " << name_ << " 添加下属: " << subordinate->getName() << std::endl;}void removeSubordinate(std::shared_ptr<OrganizationUnit> subordinate) override {auto it = std::find(subordinates_.begin(), subordinates_.end(), subordinate);if (it != subordinates_.end()) {subordinates_.erase(it);std::cout << "🗑️ " << name_ << " 移除下属: " << subordinate->getName() << std::endl;}}std::vector<std::shared_ptr<OrganizationUnit>> getSubordinates() const override {return subordinates_;}bool isComposite() const override {return true;}// 经理特有方法int getTeamSize() const {return subordinates_.size();}double getTeamTotalSalary() const {double total = getSalary();for (const auto& subordinate : subordinates_) {total += subordinate->getSalary();}return total;}void conductPerformanceReview() const {std::cout << "\n📊 " << name_ << " 进行团队绩效评估 (" << subordinates_.size() << "名下属):" << std::endl;for (const auto& subordinate : subordinates_) {std::cout << "  - " << subordinate->getName() << ": 评估完成" << std::endl;}}
};// 组合节点:部门
class Department : public OrganizationUnit {
private:std::string name_;std::string description_;std::shared_ptr<Manager> departmentHead_;std::vector<std::shared_ptr<OrganizationUnit>> members_;public:Department(const std::string& name, const std::string& description = ""): name_(name), description_(description) {}std::string getName() const override {return name_;}std::string getRole() const override {return "部门";}double getSalary() const override {// 部门的总薪资支出double total = 0;if (departmentHead_) {total += departmentHead_->getSalary();}for (const auto& member : members_) {total += member->getSalary();}return total;}void display(int depth = 0) const override {std::string indent = getIndent(depth);std::cout << indent << "🏢 " << name_ << " 部门";if (!description_.empty()) {std::cout << " - " << description_;}std::cout << " - 总薪资: ¥" << getSalary() << " (" << getTotalMembers() << "人)" << std::endl;// 显示部门负责人if (departmentHead_) {departmentHead_->display(depth + 1);}// 显示部门成员for (const auto& member : members_) {// 跳过已经显示的部门负责人if (member != departmentHead_) {member->display(depth + 1);}}}std::string getType() const override {return "部门";}// 组合对象特有方法void addSubordinate(std::shared_ptr<OrganizationUnit> member) override {members_.push_back(member);std::cout << "✅ 部门 " << name_ << " 添加成员: " << member->getName() << std::endl;}void removeSubordinate(std::shared_ptr<OrganizationUnit> member) override {auto it = std::find(members_.begin(), members_.end(), member);if (it != members_.end()) {members_.erase(it);std::cout << "🗑️ 部门 " << name_ << " 移除成员: " << member->getName() << std::endl;}}std::vector<std::shared_ptr<OrganizationUnit>> getSubordinates() const override {return members_;}bool isComposite() const override {return true;}// 部门特有方法void setDepartmentHead(std::shared_ptr<Manager> head) {departmentHead_ = head;// 确保部门负责人也在成员列表中if (std::find(members_.begin(), members_.end(), head) == members_.end()) {members_.push_back(head);}std::cout << "👑 设置 " << head->getName() << " 为 " << name_ << " 部门负责人" << std::endl;}int getTotalMembers() const {return members_.size();}void generateDepartmentReport() const {std::cout << "\n📈 " << name_ << " 部门报告:" << std::endl;std::cout << "   总人数: " << getTotalMembers() << std::endl;std::cout << "   总薪资支出: ¥" << getSalary() << std::endl;if (departmentHead_) {std::cout << "   部门负责人: " << departmentHead_->getName() << std::endl;}// 统计各角色人数std::map<std::string, int> roleCount;for (const auto& member : members_) {roleCount[member->getRole()]++;}std::cout << "   角色分布:" << std::endl;for (const auto& [role, count] : roleCount) {std::cout << "     - " << role << ": " << count << "人" << std::endl;}}
};

组合模式的招式解析

招式一:透明式组合模式
// 透明式组合模式:在抽象类中定义所有方法
class TransparentComposite {
public:virtual ~TransparentComposite() = default;// 公共操作virtual void operation() = 0;// 子节点管理操作(在叶子节点中抛出异常)virtual void add(std::shared_ptr<TransparentComposite> component) {throw std::runtime_error("不支持add操作");}virtual void remove(std::shared_ptr<TransparentComposite> component) {throw std::runtime_error("不支持remove操作");}virtual std::vector<std::shared_ptr<TransparentComposite>> getChildren() {throw std::runtime_error("不支持getChildren操作");}
};// 叶子节点
class TransparentLeaf : public TransparentComposite {
public:void operation() override {std::cout << "叶子节点操作" << std::endl;}
};// 组合节点
class TransparentNode : public TransparentComposite {
private:std::vector<std::shared_ptr<TransparentComposite>> children_;public:void operation() override {std::cout << "组合节点操作" << std::endl;for (const auto& child : children_) {child->operation();}}void add(std::shared_ptr<TransparentComposite> component) override {children_.push_back(component);}void remove(std::shared_ptr<TransparentComposite> component) override {auto it = std::find(children_.begin(), children_.end(), component);if (it != children_.end()) {children_.erase(it);}}std::vector<std::shared_ptr<TransparentComposite>> getChildren() override {return children_;}
};
招式二:安全式组合模式
// 安全式组合模式:只在组合节点中定义子节点管理方法
class SafeComponent {
public:virtual ~SafeComponent() = default;virtual void operation() = 0;
};class SafeLeaf : public SafeComponent {
public:void operation() override {std::cout << "安全式叶子节点操作" << std::endl;}
};class SafeComposite : public SafeComponent {
private:std::vector<std::shared_ptr<SafeComponent>> children_;public:void operation() override {std::cout << "安全式组合节点操作" << std::endl;for (const auto& child : children_) {child->operation();}}// 只有组合节点有这些方法void add(std::shared_ptr<SafeComponent> component) {children_.push_back(component);}void remove(std::shared_ptr<SafeComponent> component) {auto it = std::find(children_.begin(), children_.end(), component);if (it != children_.end()) {children_.erase(it);}}std::vector<std::shared_ptr<SafeComponent>> getChildren() {return children_;}
};
招式三:组合模式迭代器
// 组合模式迭代器:遍历组合结构
class CompositeIterator {
private:std::vector<std::shared_ptr<FileSystemComponent>> stack_;public:CompositeIterator(std::shared_ptr<FileSystemComponent> root) {if (root) {stack_.push_back(root);}}bool hasNext() const {return !stack_.empty();}std::shared_ptr<FileSystemComponent> next() {if (stack_.empty()) {return nullptr;}auto current = stack_.back();stack_.pop_back();// 如果是组合节点,将其子节点逆序加入栈中if (current->isComposite()) {auto children = current->getChildren();for (auto it = children.rbegin(); it != children.rend(); ++it) {stack_.push_back(*it);}}return current;}// 深度优先遍历void traverseDFS(std::shared_ptr<FileSystemComponent> node, int depth = 0) {if (!node) return;std::string indent(depth * 2, ' ');std::cout << indent << (node->isComposite() ? "📁 " : "📄 ") << node->getName() << std::endl;if (node->isComposite()) {for (const auto& child : node->getChildren()) {traverseDFS(child, depth + 1);}}}// 查找特定类型的组件std::vector<std::shared_ptr<FileSystemComponent>> findByType(std::shared_ptr<FileSystemComponent> root, const std::string& type) {std::vector<std::shared_ptr<FileSystemComponent>> result;CompositeIterator it(root);while (it.hasNext()) {auto component = it.next();if (component->getType() == type) {result.push_back(component);}}return result;}
};

完整测试代码

// 测试组合模式
void testCompositePattern() {std::cout << "=== 组合模式测试开始 ===" << std::endl;// 测试文件系统组合std::cout << "\n--- 文件系统组合测试 ---" << std::endl;// 创建文件auto file1 = std::make_shared<File>("document.txt", 1024, "txt");auto file2 = std::make_shared<File>("image.jpg", 2048000, "jpg");auto file3 = std::make_shared<File>("video.mp4", 102400000, "mp4");auto file4 = std::make_shared<File>("readme.md", 512, "md");// 创建目录auto documentsDir = std::make_shared<Directory>("Documents");auto imagesDir = std::make_shared<Directory>("Images");auto videosDir = std::make_shared<Directory>("Videos");auto homeDir = std::make_shared<Directory>("Home");// 构建文件系统结构documentsDir->addComponent(file1);documentsDir->addComponent(file4);imagesDir->addComponent(file2);videosDir->addComponent(file3);homeDir->addComponent(documentsDir);homeDir->addComponent(imagesDir);homeDir->addComponent(videosDir);// 创建符号链接auto symlink = std::make_shared<Symlink>("doc_link", file1);homeDir->addComponent(symlink);// 创建压缩目录auto compressedDir = std::make_shared<CompressedDirectory>("Backup", 0.3);compressedDir->addComponent(file1);compressedDir->addComponent(file2);homeDir->addComponent(compressedDir);// 显示文件系统std::cout << "\n📂 文件系统结构:" << std::endl;homeDir->display();// 测试目录特有方法std::cout << "\n--- 目录操作测试 ---" << std::endl;homeDir->listContents();auto foundFile = homeDir->findComponent("document.txt");if (foundFile) {std::cout << "🔍 找到文件: " << foundFile->getName() << std::endl;}// 测试组合迭代器std::cout << "\n--- 组合迭代器测试 ---" << std::endl;CompositeIterator iterator(homeDir);std::cout << "深度优先遍历:" << std::endl;iterator.traverseDFS(homeDir);auto allFiles = iterator.findByType(homeDir, "文件");std::cout << "\n📊 找到 " << allFiles.size() << " 个文件" << std::endl;// 测试组织架构组合std::cout << "\n--- 组织架构组合测试 ---" << std::endl;// 创建员工auto emp1 = std::make_shared<Employee>("张三", "软件工程师", 15000, "技术部");auto emp2 = std::make_shared<Employee>("李四", "前端工程师", 14000, "技术部");auto emp3 = std::make_shared<Employee>("王五", "测试工程师", 12000, "技术部");auto emp4 = std::make_shared<Employee>("赵六", "UI设计师", 13000, "设计部");// 创建实习生auto intern1 = std::make_shared<Intern>("钱七", "清华大学", 5000, 6, "技术部");// 创建经理auto techManager = std::make_shared<Manager>("技术总监", "技术总监", 30000, "技术部");auto designManager = std::make_shared<Manager>("设计总监", "设计总监", 28000, "设计部");// 构建团队结构techManager->addSubordinate(emp1);techManager->addSubordinate(emp2);techManager->addSubordinate(emp3);techManager->addSubordinate(intern1);designManager->addSubordinate(emp4);// 创建部门auto techDepartment = std::make_shared<Department>("技术部", "负责产品研发");auto designDepartment = std::make_shared<Department>("设计部", "负责产品设计");auto company = std::make_shared<Department>("公司", "科技公司");// 构建部门结构techDepartment->setDepartmentHead(techManager);techDepartment->addSubordinate(emp1);techDepartment->addSubordinate(emp2);techDepartment->addSubordinate(emp3);techDepartment->addSubordinate(intern1);designDepartment->setDepartmentHead(designManager);designDepartment->addSubordinate(emp4);company->addSubordinate(techDepartment);company->addSubordinate(designDepartment);// 显示组织架构std::cout << "\n🏢 组织架构:" << std::endl;company->display();// 测试部门功能std::cout << "\n--- 部门功能测试 ---" << std::endl;techDepartment->generateDepartmentReport();techManager->conductPerformanceReview();// 测试员工操作std::cout << "\n--- 员工操作测试 ---" << std::endl;emp1->promote("高级软件工程师", 18000);intern1->extendInternship(3);std::cout << "\n=== 组合模式测试结束 ===" << std::endl;
}// 实战应用:资源管理器
class ResourceManager {
private:std::shared_ptr<Directory> root_;CompositeIterator iterator_;public:ResourceManager() : root_(std::make_shared<Directory>("Root")), iterator_(root_) {initializeSampleData();}void initializeSampleData() {// 创建示例文件系统结构auto documents = std::make_shared<Directory>("Documents");auto images = std::make_shared<Directory>("Images");auto music = std::make_shared<Directory>("Music");documents->addComponent(std::make_shared<File>("report.pdf", 2500000, "pdf"));documents->addComponent(std::make_shared<File>("notes.txt", 1500, "txt"));images->addComponent(std::make_shared<File>("photo1.jpg", 3500000, "jpg"));images->addComponent(std::make_shared<File>("photo2.png", 2800000, "png"));music->addComponent(std::make_shared<File>("song1.mp3", 8500000, "mp3"));music->addComponent(std::make_shared<File>("song2.flac", 45000000, "flac"));root_->addComponent(documents);root_->addComponent(images);root_->addComponent(music);}void run() {std::cout << "\n💻 资源管理器启动" << std::endl;std::cout << "==================" << std::endl;while (true) {std::cout << "\n请选择操作:" << std::endl;std::cout << "1. 显示文件系统" << std::endl;std::cout << "2. 查找文件" << std::endl;std::cout << "3. 统计文件类型" << std::endl;std::cout << "4. 退出" << std::endl;std::cout << "选择: ";int choice;std::cin >> choice;switch (choice) {case 1:displayFileSystem();break;case 2:searchFiles();break;case 3:analyzeFileTypes();break;case 4:std::cout << "👋 再见!" << std::endl;return;default:std::cout << "❌ 无效选择" << std::endl;}}}private:void displayFileSystem() {std::cout << "\n📂 文件系统结构:" << std::endl;root_->display();}void searchFiles() {std::cout << "请输入要查找的文件名: ";std::string filename;std::cin >> filename;auto found = root_->findComponent(filename);if (found) {std::cout << "✅ 找到文件: " << found->getName() << std::endl;std::cout << "   类型: " << found->getType() << std::endl;std::cout << "   大小: " << found->getSize() << " 字节" << std::endl;} else {std::cout << "❌ 未找到文件: " << filename << std::endl;}}void analyzeFileTypes() {std::map<std::string, int> typeCount;std::map<std::string, long> typeSize;CompositeIterator it(root_);while (it.hasNext()) {auto component = it.next();if (!component->isComposite()) {if (auto file = std::dynamic_pointer_cast<File>(component)) {std::string ext = file->getExtension();typeCount[ext]++;typeSize[ext] += file->getSize();}}}std::cout << "\n📊 文件类型分析:" << std::endl;for (const auto& [ext, count] : typeCount) {std::cout << "  " << ext << ": " << count << " 个文件, " << typeSize[ext] << " 字节" << std::endl;}}
};int main() {testCompositePattern();// 运行资源管理器示例ResourceManager manager;manager.run();return 0;
}

组合模式的武学心得

适用场景
  • 部分-整体层次结构:需要表示对象的部分-整体层次结构时
  • 统一处理需求:希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时
  • 树形结构操作:需要对树形结构进行遍历、搜索、统计等操作时
优点
  • 简化客户端代码:客户端可以一致地处理单个对象和组合对象
  • 易于添加新组件:新增组件类型很容易,无需修改现有代码
  • 更好的可扩展性:可以很容易地添加新的组件类型
  • 清晰的层次结构:提供了清晰的树形结构表示
缺点
  • 设计复杂性:使得设计变得更加复杂
  • 类型检查困难:在需要限制组合中的组件类型时比较困难
  • 性能考虑:对于大型层次结构,遍历操作可能会有性能问题

武林高手的点评

Bridge 赞叹道:“Composite 兄的整体部分统一确实精妙!能够如此优雅地处理层次结构,这在构建复杂系统时确实无人能及。”

Decorator 也点头称赞:“Composite 兄专注于层次结构的统一处理,而我更关注动态的功能扩展。我们都在扩展对象的能力,但方向不同。”

Composite 谦虚回应:“诸位过奖了。每个模式都有其适用场景。在处理层次结构时,我的组合模式确实能发挥重要作用。但在需要动态添加功能时,Decorator 兄的方法更加合适。”

下章预告

在Composite展示完他的组合艺术后,Decorator 珠光宝气、华服层叠地走出,他摇着一把镶满宝石的扇子,优雅登场。

“Composite 兄的层次结构确实统一,但若想给对象动态添加功能,就需要我的装饰模式了。” Decorator 笑道,“下一章,我将展示如何动态地、透明地给对象添加无限多的新功能!”

架构老人满意地点头:“善!动态功能扩展确实是软件设计的重要需求。下一章,就请 Decorator 展示他的装饰艺术!”


欲知 Decorator 如何通过装饰模式动态扩展对象功能,且听下回分解!

http://www.dtcms.com/a/447145.html

相关文章:

  • 做服务网站吉林市做网站的科技
  • 水土保持与生态建设网站wordpress运行
  • 土特产 网站源码养老院网站建设
  • 网站后台管理密码忘记腾讯云 一键wordpress
  • 有效的网站需要做到什么意思阿里云网站301重定向怎么做
  • 【全志V821_FoxPi】4-1嵌入式系统使能openssh @root
  • itc 做市场分析的网站厦门seo推广优化
  • 做网站方案北京网站建设方案排名
  • 【LangChain】P13 LangChain 提示词模板深度解析(四):MessagePlaceholder 与少量样本示例详解
  • 点击app图标进入网站怎么做无锡优化
  • flutter专栏--深入了解widget原理
  • Java面试 -- 数据结构
  • 网站在政务新媒体建设方案济南seo排名关键词
  • Vite 构建优化实战:从配置到落地的全方位性能提升指南
  • 林州网站建设哪家专业自助建站和网站开发的利弊
  • 例外:已选中、未选中和自定义
  • 织梦网站怎么关闭手机模板合肥关键词排名技巧
  • wordpress付费阅读插件seo具体是什么
  • 上海网站推广营销设计展览馆设计公司排名
  • Effective Python 第39条:通过@classmethod多态来构造同一体系中的各类对象
  • 全flash网站模板wordpress dnax
  • 做网站有的浏览器网站建设元
  • 概率论:分布与检验(持续学习中)
  • 培训网站 建武昌网站建设制作
  • 上海网站建设免网站建设那家做的好
  • 网站的关键字 设置建设部网站首页
  • jetson nano 搭建crow环境
  • 宁波网站建设流程免费签名设计软件
  • 怎样做国外电子商务网站简单房地产网站
  • 浏览器显示不安全网站建设个人网页制作价格