C++访问者模式(Visitor)

访问者模式(Visitor Pattern)是一种行为设计模式,它允许你在不改变对象结构的前提下,定义作用于这些对象的新操作。访问者模式将操作的逻辑与对象结构分离,使得添加新的操作变得更加容易。

实际应用场景

假设我们有一个文件系统,其中包含不同类型的文件和文件夹。我们希望对这些文件和文件夹执行不同的操作,例如计算总大小、显示文件信息等。使用访问者模式,我们可以将这些操作分离出来,并在不修改文件和文件夹类的情况下添加新的操作。

访问者模式的实现步骤

  1. 定义元素接口:定义一个接口或抽象类,声明一个接受访问者的方法。
  2. 实现具体元素类:具体元素类实现这个接口,并在接受访问者的方法中调用访问者的相应方法。
  3. 定义访问者接口:定义一个访问者接口,声明一组访问方法,每个方法对应一个具体元素类。
  4. 实现具体访问者类:具体访问者类实现访问者接口,并在每个访问方法中实现具体的操作。

代码示例

以下是一个使用访问者模式的文件系统示例:

#include <iostream>
#include <vector>
#include <memory>

// 访问者接口
class File;
class Folder;

class Visitor {
public:
    virtual void visit(File* file) = 0;
    virtual void visit(Folder* folder) = 0;
    virtual ~Visitor() = default;
};

// 元素接口
class Element {
public:
    virtual void accept(Visitor* visitor) = 0;
    virtual ~Element() = default;
};

// 文件类
class File : public Element {
public:
    File(const std::string& name, int size) : name(name), size(size) {}

    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }

    std::string getName() const {
        return name;
    }

    int getSize() const {
        return size;
    }

private:
    std::string name;
    int size;
};

// 文件夹类
class Folder : public Element {
public:
    Folder(const std::string& name) : name(name) {}

    void add(std::shared_ptr<Element> element) {
        elements.push_back(element);
    }

    void accept(Visitor* visitor) override {
        visitor->visit(this);
        for (auto& element : elements) {
            element->accept(visitor);
        }
    }

    std::string getName() const {
        return name;
    }

    const std::vector<std::shared_ptr<Element>>& getElements() const {
        return elements;
    }

private:
    std::string name;
    std::vector<std::shared_ptr<Element>> elements;
};

// 具体访问者类:计算总大小
class SizeVisitor : public Visitor {
public:
    void visit(File* file) override {
        totalSize += file->getSize();
    }

    void visit(Folder* folder) override {
        // 对文件夹本身不做处理,只处理其中的文件和子文件夹
    }

    int getTotalSize() const {
        return totalSize;
    }

private:
    int totalSize = 0;
};

// 具体访问者类:显示文件信息
class InfoVisitor : public Visitor {
public:
    void visit(File* file) override {
        std::cout << "File: " << file->getName() << ", Size: " << file->getSize() << " bytes" << std::endl;
    }

    void visit(Folder* folder) override {
        std::cout << "Folder: " << folder->getName() << std::endl;
    }
};

int main() {
    // 创建文件和文件夹
    auto file1 = std::make_shared<File>("file1.txt", 100);
    auto file2 = std::make_shared<File>("file2.txt", 200);
    auto folder = std::make_shared<Folder>("myFolder");
    folder->add(file1);
    folder->add(file2);

    // 使用SizeVisitor计算总大小
    SizeVisitor sizeVisitor;
    folder->accept(&sizeVisitor);
    std::cout << "Total size: " << sizeVisitor.getTotalSize() << " bytes" << std::endl;

    // 使用InfoVisitor显示文件信息
    InfoVisitor infoVisitor;
    folder->accept(&infoVisitor);

    return 0;
}

代码解析

  1. 访问者接口 Visitor

    • 定义了两个方法 visit(File* file) 和 visit(Folder* folder),分别用于访问文件和文件夹。
  2. 元素接口 Element

    • 定义了一个 accept(Visitor* visitor) 方法,具体元素类需要实现这个方法。
  3. 具体元素类 File 和 Folder

    • File 类和 Folder 类实现了 Element 接口。
    • 在 accept 方法中,调用访问者的相应方法。
  4. 具体访问者类 SizeVisitor 和 InfoVisitor

    • SizeVisitor 用于计算总大小。
    • InfoVisitor 用于显示文件信息。
  5. 客户端代码

    • 创建文件和文件夹,并将文件添加到文件夹中。
    • 使用 SizeVisitor 计算总大小。
    • 使用 InfoVisitor 显示文件信息。

总结

访问者模式通过将操作与对象结构分离,使得在不修改对象类的情况下添加新的操作变得更加容易。在这个示例中,我们定义了文件和文件夹的结构,并通过访问者模式添加了计算总大小和显示文件信息的操作。这样可以使代码更加灵活和可扩展。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值