【声明】本题目来源于卡码网(题目页面 (kamacoder.com))
【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】
【简介】什么是组合模式
组合模式是⼀种结构型设计模式,它将对象组合成树状结构来表示“部分-整体”的层次关系。组合模式使得客户端可以统⼀处理单个对象和对象的组合,⽽⽆需区分它们的具体类型。
【基本结构】
组合模式包括下⾯⼏个⻆⾊:
理解起来⽐较抽象,我们⽤“省份-城市”举个例⼦,省份中包含了多个城市,如果将之⽐喻成⼀个树形结构,城市就是叶⼦节点,它是省份的组成部分,⽽“省份”就是合成节点,可以包含其他城市,形成⼀个整体,省份和城市都是组件,它们都有⼀个共同的操作,⽐如获取信息。
- Component 组件: 组合模式的“根节点”,定义组合中所有对象的通⽤接⼝,可以是抽象类或接⼝。该类中定义了⼦类的共性内容。
- Leaf 叶⼦:实现了Component接⼝的叶⼦节点,表示组合中的叶⼦对象,叶⼦节点没有⼦节点。
- Composite 合成: 作⽤是存储⼦部件,并且在Composite中实现了对⼦部件的相关操作,⽐如添加、删除、获取⼦组件等。
通过组合模式,整个省份的获取信息操作可以⼀次性地执⾏,⽽⽆需关⼼省份中的具体城市。这样就实现了对国家省份和城市的管理和操作。
【简易实现】
利用Java代码作以说明:
1. 组件接口
// 组件接⼝
interface Component {
void operation();
}
2. 叶子节点
// 叶⼦节点
class Leaf implements Component {
@Override
public void operation() {
System.out.println("Leaf operation");
}
}
3. 组合节点
// 组合节点:包含叶⼦节点的操作⾏为
class Composite implements Component {
private List<Component> components = new ArrayList<>();
public void add(Component component) {
components.add(component);
}
public void remove(Component component) {
components.remove(component);
}
@Override
public void operation() {
System.out.println("Composite operation");
for (Component component : components) {
component.operation();
}
}
}
4. 客户端代码
// 客户端代码
public class Client {
public static void main(String[] args) {
// 创建叶⼦节点
Leaf leaf = new Leaf();
// 创建组合节点,并添加叶⼦节点
Composite composite = new Composite();
composite.add(leaf);
composite.operation(); // 统⼀调⽤
}
}
【使用场景】
组合模式可以使得客户端可以统⼀处理单个对象和组合对象,⽆需区分它们之间的差异,⽐如在图形编辑器中,图形对象可以是简单的线、圆形,也可以是复杂的组合图形,这个时候可以对组合节点添加统⼀的操作。
总的来说,组合模式适⽤于任何需要构建具有部分-整体层次结构的场景,⽐如组织架构管理、⽂件系统的⽂件和⽂件夹组织等。
【C++ 编码部分】
1. 题目描述
小明所在的公司内部有多个部门,每个部门下可能有不同的子部门或者员工。请你设计一个组合模式来管理这些部门和员工,实现对公司组织结构的统一操作。部门和员工都具有一个通用的接口,可以获取他们的名称以及展示公司组织结构。
2. 输入描述
第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。 接下来的 N 行,每行描述一个部门或员工的信息。部门的信息格式为 D 部门名称,员工的信息格式为 E 员工名称,其中 D 或 E 表示部门或员工。
3. 输出描述
输出公司的组织结构,展示每个部门下的子部门和员工。
4. C++ 编码实例
/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file CompositeMode.hpp
* @brief 组合模式
* @autor 写代码的小恐龙er
* @date 2024/01/12
*/
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 前置声明
// Component 组件: 组合模式的“根节点”,定义组合中所有对象的通⽤接⼝,可以是抽象类或接⼝
class Component;
// 叶⼦节点1 -- 部门 (还可以包含子部门和员工)
class Department;
// 叶子节点2 -- 员工
class Employee;
// 组合节点 -- 包含叶子节点的操作行为
class Composite;
// Component 组件: 组合模式的“根节点”
class Component
{
public:
// 提供信息展示的公共接口
virtual void ShowInfo(int depth) = 0;
};
// 叶⼦节点1 -- 部门 (还可以包含子部门和员工)
class Department : public Component
{
// 成员属性
private:
// 部门名称
string _name;
// 子部门 -- 新建子部门的室友 使用派生类来新建 基类
std::vector<Component *> _childrenVec;
//成员函数
public:
// 重载构造函数 以便通过部门名称新建部门
Department(){}
Department(string name){
this->_name = name;
}
// 添加子部门
void AddSubDepartment(Component * component){
_childrenVec.push_back(component);
}
// 重载部门信息展示函数
void ShowInfo(int depth) override {
// ======= 展示自己的信息 =======
string info = "";
for(int i = 0; i < depth; i++){
info += " ";
}
std::cout << info << _name << endl;
// ======= 展示子部门的信息 =======
for(int j = 0; j < _childrenVec.size(); j++){
_childrenVec[j]->ShowInfo(depth + 1);
}
}
};
// 叶子节点2 -- 员工
class Employee : public Component
{
// 成员属性
private:
// 员工名称
string _name;
//成员函数
public:
// 重载构造函数 以便通过员工名称新建员工
Employee(string name){
this->_name = name;
}
// 重载员工信息展示函数
void ShowInfo(int depth) override {
// ======= 展示自己的信息 =======
string info = "";
for(int i = 0; i < depth; i++){
info += " ";
}
std::cout << info << " " << _name << endl;
}
};
// 组合节点 -- 包含叶子节点的操作行为
class Composite
{
// 成员属性
private:
// 公司名称 -- 管理这些叶子节点的 根节点
string _name;
// 根节点
Department *_rootDepartment;
// 成员函数
public:
// 重载构造函数 来新建某个公司
Composite(string name){
this->_name = name;
_rootDepartment = new Department(name);
}
// 析构函数
~Composite(){
if(_rootDepartment != nullptr){
delete _rootDepartment;
_rootDepartment = nullptr;
}
}
// 添加根节点下面的子节点
void AddComponent(Component *component){
_rootDepartment->AddSubDepartment(component);
}
// 信息展示初始函数
void ShowInfo(){
std::cout << "Company Structure:" << endl;
// 此时开头的根节点 不需要做缩进 故而 参数传入0
_rootDepartment->ShowInfo(0);
}
};
int main()
{
// 公司名称
string companyName = "";
//输入
std::cin >> companyName;
// 部门和员工总数
int number = 0;
// 输入
std::cin >> number;
// 组合节点 -- 传入公司名称 新建根节点
Composite *company = new Composite(companyName);
for(int i = 0; i < number; i++)
{
// 信息类型
char type = ' ';
// 名称
string name = "";
// 输入
std::cin >> type >> name;
// 新建部门 -- 名称构造
Component *component = nullptr;
Employee *employee = nullptr;
if(type == 'D'){
// 新建部门派生类
Component *component = new Department(name);
company->AddComponent(component);
}
else if(type == 'E'){
// 新建员工派生类
Component *employee = new Employee(name);
company->AddComponent(employee);
}
else continue;
// 析构掉New出来的内存
if(component != nullptr) {
delete component;
component = nullptr;
}
if(component != nullptr) {
delete employee;
employee = nullptr;
}
}
// 添加完根节点和子节点后开始结构信息展示
company->ShowInfo();
// 析构掉New出来的内存
delete company;
company = nullptr;
return 0;
}
......文章来源:https://www.toymoban.com/news/detail-799467.html
To be continued.文章来源地址https://www.toymoban.com/news/detail-799467.html
到了这里,关于C++ 设计模式之组合模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!