一、什么是组合模式
组合多个对象形成树形结构以表示“部分-整体”的结构层次。组合模式对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。可以简单理解为一组对象集合。其应用场景的特殊性,数据必须能表示成树形结构
树形结构在软件中随处可见,例如操作系统中的目录结构、应用软件中的菜单、办公系统中的公司组织结构等等,这样的组织形式的特点在于:叶子节点不再包含成员对象,而容器节点可以包含成员对象,这些对象可以是叶子节点,也可以是容器节点。
下面是UML类图


用来表达和处理树形结构的数据。


二、模式结构
Component(抽象构件):可以是接口或抽象类,定义了构件的一些公共接口,这些接口是管理或者访问它的子构件的方法(如果有子构件),具体的实现在叶子构件和容器构件中进行。
Leaf(叶子构件):它代表树形结构中的叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法(非叶子构件功能,属于容器构件的功能),可以通过抛出异常、提示错误等方式进行处理。
Composite(容器构件) :表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为。
三、代码实现
模拟对文件和文件夹的显示
Component(抽象构件): AbstractFile
Leaf(叶子构件):ImageFile TextFile
Composite(容器构件):Folder
#include<iostream>
#include <list>
using namespace std;
/// Component(抽象构件): AbstractFile
class AbstractFile {
public:
virtual ~AbstractFile() = default;
virtual void add(AbstractFile *file) = 0;
virtual void remove(AbstractFile *file) = 0;
virtual void display() = 0;
protected:
AbstractFile() = default;
};
/// Leaf(叶子构件): ImageFile TextFile
class ImageFile :public AbstractFile
{
private:
string name;
public:
ImageFile(string str) :name(str)
{
}
void add(AbstractFile *file)
{
cout << "不支持\n";
return;
}
void remove(AbstractFile *file)
{
cout << "不支持\n";
return;
}
void display()
{
cout <<"图像文件:"<< name.c_str() << endl;
return;
}
};
class TextFile :public AbstractFile
{
private:
string name;
public:
TextFile(string str) :name(str)
{
}
void add(AbstractFile *file)
{
cout << "不支持\n";
return;
}
void remove(AbstractFile *file)
{
cout << "不支持\n";
return;
}
void display()
{
cout << "文本文件:" << name.c_str() << endl;
return;
}
};
/// Composite(容器构件): Folder
class Folder :public AbstractFile
{
private:
string name;
list<AbstractFile *> m_list;
public:
Folder(string str) :name(str)
{
}
void add(AbstractFile *file)
{
m_list.push_back(file);
}
void remove(AbstractFile *file)
{
m_list.remove(file);
}
void display()
{
cout << "------文件夹:" << name.c_str() <<"--------" <<endl;
for (auto it :m_list)
{
it->display();
}
}
};
void main()
{
//针对抽象构件编程
AbstractFile *file1, *file2, *file3, *file4, *folder1, *folder2, *folder3, *folder0;
folder0 = new Folder("根目录文件夹");
folder1 = new Folder("图像文件夹");
folder2 = new Folder("文本文件夹");
folder3 = new Folder("视频文件夹");
file1 = new ImageFile("图片01.jpg");
file2 = new ImageFile("图片02.gif");
file3 = new TextFile("文本01.txt");
file4 = new TextFile("文本02.doc");
folder1->add(file1);
folder1->add(file2);
folder2->add(file3);
folder2->add(file4);
folder0->add(folder1);
folder0->add(folder2);
folder0->add(folder3);
//从 根目录文件夹 节点开始进行模拟杀毒操作
folder0->display();
delete file1;
delete file2;
delete file3;
delete file4;
delete folder0;
delete folder1;
delete folder2;
delete folder3;
system("pause");
}
结果:

案例二:
#include <iostream>
#include <string>
#include <list>
using namespace std;
class AbstractFile
{
public:
virtual void add(AbstractFile *pFile) = 0;
virtual void remove(AbstractFile *pFile) = 0;
virtual void display() = 0
{
cout << m_strName << endl;;
}
AbstractFile(string name) :m_strName(name){}
virtual ~AbstractFile(){}
private:
string m_strName;
};
class TextFile :public AbstractFile
{
public:
void add(AbstractFile *pFile)
{
}
void remove(AbstractFile *pFile)
{
}
void display()
{
cout << " - ";
AbstractFile::display();
}
TextFile(string strName) :AbstractFile(strName)
{
}
};
class ImageFile :public AbstractFile
{
public:
void add(AbstractFile *pFile)
{
}
void remove(AbstractFile *pFile)
{
}
void display()
{
cout << " - ";
AbstractFile::display();
}
ImageFile(string strName) :AbstractFile(strName)
{
}
};
class Folder :public AbstractFile
{
public:
void add(AbstractFile *pFile)
{
m_list.push_back(pFile);
}
void remove(AbstractFile *pFile)
{
m_list.remove(pFile);
}
void display()
{
cout << "+ ";
AbstractFile::display();
for (auto node :m_list)
{
node->display();
}
}
Folder(string strName) :AbstractFile(strName)
{
}
private:
list<AbstractFile*>m_list;
};
void main()
{
TextFile *pTxt = new TextFile("1.txt");
ImageFile *pImg = new ImageFile("1.jpg");
Folder *pDir1 = new Folder("私密文件夹");
pDir1->add(pTxt);
pDir1->add(pImg);
TextFile *pTxt1 = new TextFile("2.txt");
ImageFile *pImg1 = new ImageFile("2.jpg");
Folder *pDir2 = new Folder("种子文件夹");
pDir2->add(pTxt1);
pDir2->add(pImg1);
Folder *pRoot = new Folder("不能看");
pRoot->add(pDir1);
pRoot->add(pDir2);
pRoot->display();
//懒得释放。。。
system("pause");
}

本文介绍了组合模式,一种用于构建部分-整体层次结构的软件设计模式。通过抽象构件、叶子构件和容器构件的定义,展示了如何在C++中实现文件和文件夹的树形结构。代码示例演示了如何创建、添加和显示文件系统中的文件和文件夹,以及如何遍历和展示整个结构。

被折叠的 条评论
为什么被折叠?



