您的位置:首页 > 科技 > IT业 > 到哪里建网站_高明铝业网站建站_郑州网站推广哪家专业_seo优化内页排名

到哪里建网站_高明铝业网站建站_郑州网站推广哪家专业_seo优化内页排名

2024/12/23 15:32:24 来源:https://blog.csdn.net/chenai886/article/details/144602727  浏览:    关键词:到哪里建网站_高明铝业网站建站_郑州网站推广哪家专业_seo优化内页排名
到哪里建网站_高明铝业网站建站_郑州网站推广哪家专业_seo优化内页排名

组合模式是一种非常有用的设计模式,用于解决**“部分-整体”**问题。它允许我们用树形结构来表示对象的层次结构,并且让客户端可以统一地操作单个对象和组合对象。


组合模式的核心思想

什么是组合模式?

组合模式的目的是将对象组织成树形结构,表示“部分-整体”的层次结构,使客户端能够以一致的方式处理单个对象和组合对象。

组合模式的结构

组合模式一般由以下三个部分组成:

  1. 组件(Component):定义了组合对象和叶子对象的通用接口。
  2. 叶子节点(Leaf):表示树的基本单元,不能再包含其他子对象。
  3. 组合节点(Composite):表示有子节点的对象,它实现了组件接口并且可以操作其子节点。
组合模式的特点
  1. 递归结构:树形结构的每个节点既可以是叶子,也可以是子树。
  2. 统一接口:客户端通过相同的接口处理单个对象和组合对象。

案例:公司组织架构

案例背景

我们需要设计一个程序来模拟公司组织架构:

  1. 公司有不同的部门(如总部、人力资源部、技术部等)。
  2. 每个部门可以包含其他部门和员工。
  3. 我们希望能够清晰地输出公司组织的层次结构。

代码分块及讲解

1. 抽象组件类

这是组合模式的核心部分,所有叶子节点和组合节点都必须实现这个抽象类。通过这个类,我们可以定义统一的操作接口。

// 抽象组件类:Component
class Component {
public:// 展示信息的接口,所有子类都需要实现virtual void display(int depth) const = 0;// 以下两个接口仅供组合节点使用,叶子节点不需要实现virtual void add(std::shared_ptr<Component> component) {}virtual void remove(std::shared_ptr<Component> component) {}// 虚析构函数,保证子类正确释放资源virtual ~Component() = default;
};

分析:

  • display(int depth):定义了展示对象信息的方法,depth用于控制输出的层次缩进。
  • addremove:用于操作子节点,默认为空实现,叶子节点无需实现这两个方法。
  • 虚析构函数:确保使用多态时,子类可以正确释放资源。

2. 叶子节点类

叶子节点是树形结构的最底层元素,它不包含任何子节点。比如在组织架构中,员工就是叶子节点。

// 叶子节点类:Employee(员工)
class Employee : public Component {
private:std::string name; // 员工姓名public:explicit Employee(const std::string& name) : name(name) {}// 实现展示接口void display(int depth) const override {std::cout << std::string(depth, '-') << "员工: " << name << std::endl;}
};

分析:

  • name:记录员工姓名。
  • display:实现了抽象类的接口,输出员工的信息,并用depth控制层次缩进。
  • 叶子节点没有子节点:因此不需要实现addremove方法。

3. 组合节点类

组合节点可以包含其他节点(叶子节点或组合节点),并负责管理它们。比如一个部门可以包含其他部门或员工。

// 组合节点类:Department(部门)
class Department : public Component {
private:std::string name; // 部门名称std::vector<std::shared_ptr<Component>> children; // 子节点集合public:explicit Department(const std::string& name) : name(name) {}// 添加子节点void add(std::shared_ptr<Component> component) override {children.push_back(component);}// 移除子节点void remove(std::shared_ptr<Component> component) override {children.erase(std::remove(children.begin(), children.end(), component),children.end());}// 展示部门及其子节点信息void display(int depth) const override {std::cout << std::string(depth, '-') << "部门: " << name << std::endl;// 遍历并递归调用子节点的display方法for (const auto& child : children) {child->display(depth + 2); // 子节点缩进}}
};

分析:

  • name:记录部门名称。
  • children:用一个vector存储部门的子节点(可以是员工或其他部门)。
  • addremove:用于动态添加或移除子节点。
  • display
    • 先输出当前部门的信息。
    • 然后递归调用所有子节点的display方法,以树形方式展示整个结构。

4. 客户端代码

在客户端代码中,我们将创建叶子节点(员工)和组合节点(部门),并将它们组织成树形结构,最后输出公司组织架构。

int main() {// 创建叶子节点(员工)auto emp1 = std::make_shared<Employee>("张三");auto emp2 = std::make_shared<Employee>("李四");auto emp3 = std::make_shared<Employee>("王五");// 创建组合节点(部门)auto department1 = std::make_shared<Department>("人力资源部");auto department2 = std::make_shared<Department>("技术部");// 给部门添加员工department1->add(emp1);department2->add(emp2);department2->add(emp3);// 创建公司根节点auto company = std::make_shared<Department>("总部");// 将部门加入公司company->add(department1);company->add(department2);// 展示公司组织架构company->display(0);return 0;
}

分析:

  1. 创建叶子节点(员工)
    • 创建三个员工对象,分别为“张三”、“李四”和“王五”。
  2. 创建组合节点(部门)
    • 创建两个部门,分别为“人力资源部”和“技术部”。
  3. 构建树结构
    • 将“张三”加入人力资源部。
    • 将“李四”和“王五”加入技术部。
    • 将两个部门加入公司的根节点“总部”。
  4. 输出组织架构
    • 调用display方法,从根节点开始递归输出整棵树的结构。

运行结果

运行程序后,输出如下:

部门: 总部
--部门: 人力资源部
----员工: 张三
--部门: 技术部
----员工: 李四
----员工: 王五

输出说明:

  • 根节点“总部”包含两个子节点:人力资源部和技术部。
  • 每个部门又包含各自的员工信息,清晰地展示了整个公司组织结构。

组合模式的优缺点

优点
  1. 统一性:客户端代码可以统一处理单个对象和组合对象,简化了逻辑。
  2. 扩展性:可以轻松增加新的叶子节点或组合节点。
  3. 灵活性:支持动态调整树形结构(如添加、删除节点)。
缺点
  1. 复杂性:对于简单结构来说,使用组合模式会增加不必要的复杂性。
  2. 通用性限制:某些特定操作可能只适合叶子节点,但为了统一接口,组合节点也必须实现这些方法。

总结

组合模式通过将单个对象和组合对象统一处理,解决了“部分-整体”问题,特别适合树形结构的数据处理场景。通过案例代码我们可以看到:

  1. 使用组合模式可以清晰地表示公司组织架构。
  2. 递归调用的display方法是组合模式的核心,能够清晰输出树形层次结构。
  3. 组合模式广泛应用于组织架构、文件系统、GUI组件树等场景。

源码分享

#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <algorithm> // 用于删除元素// 抽象组件类:Component
class Component {
public:// 展示信息的接口,所有子类都需要实现virtual void display(int depth) const = 0;// 以下两个接口仅供组合节点使用,叶子节点不需要实现virtual void add(std::shared_ptr<Component> component) {}virtual void remove(std::shared_ptr<Component> component) {}// 虚析构函数,保证子类正确释放资源virtual ~Component() = default;
};// 叶子节点类:Employee(员工)
class Employee : public Component {
private:std::string name; // 员工姓名public:explicit Employee(const std::string& name) : name(name) {}// 实现展示接口void display(int depth) const override {// 使用深度(depth)控制输出的缩进层次std::cout << std::string(depth, '-') << "员工: " << name << std::endl;}
};// 组合节点类:Department(部门)
class Department : public Component {
private:std::string name; // 部门名称std::vector<std::shared_ptr<Component>> children; // 子节点集合public:explicit Department(const std::string& name) : name(name) {}// 添加子节点void add(std::shared_ptr<Component> component) override {children.push_back(component);}// 移除子节点void remove(std::shared_ptr<Component> component) override {children.erase(std::remove(children.begin(), children.end(), component),children.end());}// 展示部门及其子节点信息void display(int depth) const override {// 输出当前部门信息std::cout << std::string(depth, '-') << "部门: " << name << std::endl;// 遍历所有子节点,并递归调用它们的display方法for (const auto& child : children) {child->display(depth + 2); // 子节点缩进更深}}
};// 客户端代码
int main() {// 创建叶子节点(员工)auto emp1 = std::make_shared<Employee>("张三"); // 人力资源部的员工auto emp2 = std::make_shared<Employee>("李四"); // 技术部的员工auto emp3 = std::make_shared<Employee>("王五"); // 技术部的员工// 创建组合节点(部门)auto department1 = std::make_shared<Department>("人力资源部");auto department2 = std::make_shared<Department>("技术部");// 给部门添加员工department1->add(emp1); // 添加张三到人力资源部department2->add(emp2); // 添加李四到技术部department2->add(emp3); // 添加王五到技术部// 创建公司根节点auto company = std::make_shared<Department>("总部");// 将部门加入公司company->add(department1); // 将人力资源部加入总部company->add(department2); // 将技术部加入总部// 展示公司组织架构company->display(0); // 从根节点开始展示整个组织架构return 0;
}

运行结果

运行此代码,程序将输出如下内容:

部门: 总部
--部门: 人力资源部
----员工: 张三
--部门: 技术部
----员工: 李四
----员工: 王五

本文由mdnice多平台发布

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com