从零开始理解与实现简易C++组合模式

组合模式(Composite Pattern)在实际生活中的应用非常广泛,尤其是在需要表示“整体-部分”层次结构的场景中。我们可以用一个简单且易懂的实际工作应用来讲解:文件系统。

组合模式应用场景:文件系统

在一个文件系统中,我们有文件和文件夹。文件夹里可以包含文件和其他文件夹,这样就形成了一个“整体-部分”的层次结构。对于用户来说,无论是操作单个文件还是整个文件夹,都应该有一致的处理方式。

文件系统示例

我们将实现以下类:

  1. Component: 文件系统中对象的抽象接口,可以是文件或者文件夹。
  2. File: 表示文件的具体实现。
  3. 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;
}

解释

  1. 抽象组件类(FileSystem)

    • FileSystem 是一个抽象类,定义了一个纯虚函数 showDetails,要求所有子类实现这个方法。
  2. 文件类(File)

    • File 类继承自 FileSystem,实现了 showDetails 方法,显示文件名称。
  3. 文件夹类(Directory)

    • Directory 类也是继承自 FileSystem,它包含一个 vector 来存储 FileSystem 指针。
    • add 方法用于向目录中添加新的文件或子目录。
    • showDetails 方法递归地显示目录内容的细节。
    • ~Directory 析构函数用于递归地删除目录内容,防止内存泄漏。
  4. 客户端代码

    • 创建文件对象和目录对象,并构建一个树形结构。
    • 使用 showDetails 方法显示文件系统的层次结构。
    • 最后,清理内存。

通过这个文件系统的例子,我们可以看到组合模式如何让我们对单个对象(文件)和组合对象(文件夹)具有一致的处理方式,从而简化了复杂对象结构的处理。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值