组合模式(Composite Pattern)在实际生活中的应用非常广泛,尤其是在需要表示“整体-部分”层次结构的场景中。我们可以用一个简单且易懂的实际工作应用来讲解:文件系统。
组合模式应用场景:文件系统
在一个文件系统中,我们有文件和文件夹。文件夹里可以包含文件和其他文件夹,这样就形成了一个“整体-部分”的层次结构。对于用户来说,无论是操作单个文件还是整个文件夹,都应该有一致的处理方式。
文件系统示例
我们将实现以下类:
- Component: 文件系统中对象的抽象接口,可以是文件或者文件夹。
- File: 表示文件的具体实现。
- Directory: 表示文件夹的具体实现,里面可以包含多个文件和文件夹。
代码示例
抽象组件类
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class FileSystem {
public:
virtual void showDetails() = 0; // 纯虚函数,显示细节
virtual ~FileSystem() {} // 虚析构函数
};
文件类
class File : public FileSystem {
private:
string name;
public:
File(const string& name) : name(name) {}
void showDetails() override {
cout << "File: " << name << endl;
}
};
文件夹类
class Directory : public FileSystem {
private:
string name;
vector<FileSystem*> contents; // 文件系统内的内容,可能是文件或者文件夹
public:
Directory(const string& name) : name(name) {}
void add(FileSystem* component) {
contents.push_back(component);
}
void showDetails() override {
cout << "Directory: " << name << endl;
for (auto* component : contents) {
component->showDetails();
}
}
~Directory() {
for (auto* component : contents) {
delete component;
}
}
};
客户端代码
int main() {
// 创建一些文件
FileSystem* file1 = new File("file1.txt");
FileSystem* file2 = new File("file2.txt");
FileSystem* file3 = new File("file3.txt");
// 创建一个目录,并将文件添加进去
Directory* dir1 = new Directory("dir1");
dir1->add(file1);
dir1->add(file2);
// 创建另一个目录,并将上一个目录和另一个文件添加进去
Directory* dir2 = new Directory("dir2");
dir2->add(dir1);
dir2->add(file3);
// 显示目录结构
dir2->showDetails();
// 清理内存
delete dir2;
return 0;
}
完整代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class FileSystem {
public:
virtual void showDetails() = 0; // 纯虚函数,显示细节
virtual ~FileSystem() {} // 虚析构函数
};
class File : public FileSystem {
private:
string name;
public:
File(const string& name) : name(name) {}
void showDetails() override {
cout << "File: " << name << endl;
}
};
class Directory : public FileSystem {
private:
string name;
vector<FileSystem*> contents; // 文件系统内的内容,可能是文件或者文件夹
public:
Directory(const string& name) : name(name) {}
void add(FileSystem* component) {
contents.push_back(component);
}
void showDetails() override {
cout << "Directory: " << name << endl;
for (auto* component : contents) {
component->showDetails();
}
}
~Directory() {
for (auto* component : contents) {
delete component;
}
}
};
int main() {
// 创建一些文件
FileSystem* file1 = new File("file1.txt");
FileSystem* file2 = new File("file2.txt");
FileSystem* file3 = new File("file3.txt");
// 创建一个目录,并将文件添加进去
Directory* dir1 = new Directory("dir1");
dir1->add(file1);
dir1->add(file2);
// 创建另一个目录,并将上一个目录和另一个文件添加进去
Directory* dir2 = new Directory("dir2");
dir2->add(dir1);
dir2->add(file3);
// 显示目录结构
dir2->showDetails();
// 清理内存
delete dir2;
return 0;
}
解释
-
抽象组件类(FileSystem)
FileSystem
是一个抽象类,定义了一个纯虚函数showDetails
,要求所有子类实现这个方法。
-
文件类(File)
File
类继承自FileSystem
,实现了showDetails
方法,显示文件名称。
-
文件夹类(Directory)
Directory
类也是继承自FileSystem
,它包含一个vector
来存储FileSystem
指针。add
方法用于向目录中添加新的文件或子目录。showDetails
方法递归地显示目录内容的细节。~Directory
析构函数用于递归地删除目录内容,防止内存泄漏。
-
客户端代码
- 创建文件对象和目录对象,并构建一个树形结构。
- 使用
showDetails
方法显示文件系统的层次结构。 - 最后,清理内存。
通过这个文件系统的例子,我们可以看到组合模式如何让我们对单个对象(文件)和组合对象(文件夹)具有一致的处理方式,从而简化了复杂对象结构的处理。