C++中的访问者模式

59 篇文章 0 订阅
52 篇文章 1 订阅

目录

访问者模式(Visitor Pattern)

实际应用

文件系统的访问者模式

形状绘制系统

数据库操作系统

总结


访问者模式(Visitor Pattern)

访问者模式是一种行为设计模式,它允许你在不修改元素类的前提下,定义作用于这些类上的新的操作。访问者模式将操作的算法与对象结构分离,使得算法可以在不修改对象结构的前提下扩展。

实际应用

文件系统的访问者模式

-- 文件系统结构,计算总大小和打印文件结构。

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

// 前向声明访问者类
class File;
class Folder;
class FileSystemVisitor;

// 元素接口
class FileSystemElement {
public:
    virtual void accept(FileSystemVisitor& visitor) = 0;
    virtual ~FileSystemElement() = default;
};

// 具体元素类:文件
class File : public FileSystemElement {
private:
    std::string name;
    int size;

public:
    File(const std::string& name, int size) : name(name), size(size) {}

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

    int getSize() const {
        return size;
    }

    void accept(FileSystemVisitor& visitor) override;
};

// 具体元素类:文件夹
class Folder : public FileSystemElement {
private:
    std::string name;
    std::vector<std::shared_ptr<FileSystemElement>> elements;

public:
    Folder(const std::string& name) : name(name) {}

    void addElement(const std::shared_ptr<FileSystemElement>& element) {
        elements.push_back(element);
    }

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

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

    void accept(FileSystemVisitor& visitor) override;
};

// 访问者接口
class FileSystemVisitor {
public:
    virtual void visit(File& file) = 0;
    virtual void visit(Folder& folder) = 0;
    virtual ~FileSystemVisitor() = default;
};

// 具体访问者类:计算总大小
class SizeCalculatorVisitor : public FileSystemVisitor {
private:
    int totalSize = 0;

public:
    void visit(File& file) override {
        totalSize += file.getSize();
    }

    void visit(Folder& folder) override {
        for (const auto& element : folder.getElements()) {
            element->accept(*this);
        }
    }

    int getTotalSize() const {
        return totalSize;
    }
};

// 具体访问者类:打印文件结构
class StructurePrinterVisitor : public FileSystemVisitor {
private:
    void printIndent(int level) {
        for (int i = 0; i < level; ++i) {
            std::cout << "  ";
        }
    }

public:
    void visit(File& file) override {
        printIndent(1);
        std::cout << "File: " << file.getName() << " (" << file.getSize() << " bytes)" << std::endl;
    }

    void visit(Folder& folder) override {
        printIndent(0);
        std::cout << "Folder: " << folder.getName() << std::endl;
        for (const auto& element : folder.getElements()) {
            element->accept(*this);
        }
    }
};

// File 和 Folder 的 accept 方法实现
void File::accept(FileSystemVisitor& visitor) {
    visitor.visit(*this);
}

void Folder::accept(FileSystemVisitor& visitor) {
    visitor.visit(*this);
}

// 客户端代码
int main() {
    auto root = std::make_shared<Folder>("root");
    auto file1 = std::make_shared<File>("file1.txt", 100);
    auto file2 = std::make_shared<File>("file2.txt", 200);
    auto subFolder = std::make_shared<Folder>("subfolder");
    auto file3 = std::make_shared<File>("file3.txt", 300);

    root->addElement(file1);
    root->addElement(file2);
    root->addElement(subFolder);
    subFolder->addElement(file3);

    // 计算总大小
    SizeCalculatorVisitor sizeCalculator;
    root->accept(sizeCalculator);
    std::cout << "Total size: " << sizeCalculator.getTotalSize() << " bytes" << std::endl;

    // 打印文件结构
    StructurePrinterVisitor structurePrinter;
    root->accept(structurePrinter);

    return 0;
}

形状绘制系统

-- 形状绘制系统,计算面积和绘制形状。

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

// 前向声明访问者类
class Circle;
class Rectangle;
class ShapeVisitor;

// 元素接口
class Shape {
public:
    virtual void accept(ShapeVisitor& visitor) = 0;
    virtual ~Shape() = default;
};

// 具体元素类:圆形
class Circle : public Shape {
private:
    double radius;

public:
    Circle(double radius) : radius(radius) {}

    double getRadius() const {
        return radius;
    }

    void accept(ShapeVisitor& visitor) override;
};

// 具体元素类:矩形
class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double width, double height) : width(width), height(height) {}

    double getWidth() const {
        return width;
    }

    double getHeight() const {
        return height;
    }

    void accept(ShapeVisitor& visitor) override;
};

// 访问者接口
class ShapeVisitor {
public:
    virtual void visit(Circle& circle) = 0;
    virtual void visit(Rectangle& rectangle) = 0;
    virtual ~ShapeVisitor() = default;
};

// 具体访问者类:计算面积
class AreaCalculatorVisitor : public ShapeVisitor {
private:
    double totalArea = 0;

public:
    void visit(Circle& circle) override {
        double area = M_PI * std::pow(circle.getRadius(), 2);
        totalArea += area;
    }

    void visit(Rectangle& rectangle) override {
        double area = rectangle.getWidth() * rectangle.getHeight();
        totalArea += area;
    }

    double getTotalArea() const {
        return totalArea;
    }
};

// 具体访问者类:绘制形状
class ShapeDrawerVisitor : public ShapeVisitor {
public:
    void visit(Circle& circle) override {
        std::cout << "Drawing Circle with radius " << circle.getRadius() << std::endl;
    }

    void visit(Rectangle& rectangle) override {
        std::cout << "Drawing Rectangle with width " << rectangle.getWidth() << " and height " << rectangle.getHeight() << std::endl;
    }
};

// Circle 和 Rectangle 的 accept 方法实现
void Circle::accept(ShapeVisitor& visitor) {
    visitor.visit(*this);
}

void Rectangle::accept(ShapeVisitor& visitor) {
    visitor.visit(*this);
}

// 客户端代码
int main() {
    std::vector<std::shared_ptr<Shape>> shapes;
    shapes.push_back(std::make_shared<Circle>(5.0));
    shapes.push_back(std::make_shared<Rectangle>(4.0, 6.0));

    // 计算总面积
    AreaCalculatorVisitor areaCalculator;
    for (auto& shape : shapes) {
        shape->accept(areaCalculator);
    }
    std::cout << "Total area: " << areaCalculator.getTotalArea() << std::endl;

    // 绘制形状
    ShapeDrawerVisitor shapeDrawer;
    for (auto& shape : shapes) {
        shape->accept(shapeDrawer);
    }

    return 0;
}

数据库操作系统

-- 数据库操作系统,日志记录和权限检查。

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

// 前向声明访问者类
class InsertOperation;
class UpdateOperation;
class DatabaseOperationVisitor;

// 元素接口
class DatabaseOperation {
public:
    virtual void accept(DatabaseOperationVisitor& visitor) = 0;
    virtual ~DatabaseOperation() = default;
};

// 具体元素类:插入操作
class InsertOperation : public DatabaseOperation {
private:
    std::string table;
    std::string data;

public:
    InsertOperation(const std::string& table, const std::string& data) : table(table), data(data) {}

    const std::string& getTable() const {
        return table;
    }

    const std::string& getData() const {
        return data;
    }

    void accept(DatabaseOperationVisitor& visitor) override;
};

// 具体元素类:更新操作
class UpdateOperation : public DatabaseOperation {
private:
    std::string table;
    std::string data;

public:
    UpdateOperation(const std::string& table, const std::string& data) : table(table), data(data) {}

    const std::string& getTable() const {
        return table;
    }

    const std::string& getData() const {
        return data;
    }

    void accept(DatabaseOperationVisitor& visitor) override;
};

// 访问者接口
class DatabaseOperationVisitor {
public:
    virtual void visit(InsertOperation& operation) = 0;
    virtual void visit(UpdateOperation& operation) = 0;
    virtual ~DatabaseOperationVisitor() = default;
};

// 具体访问者类:日志记录
class LoggingVisitor : public DatabaseOperationVisitor {
public:
    void visit(InsertOperation& operation) override {
        std::cout << "Logging: Insert operation on table " << operation.getTable() << " with data " << operation.getData() << std::endl;
    }

    void visit(UpdateOperation& operation) override {
        std::cout << "Logging: Update operation on table " << operation.getTable() << " with data " << operation.getData() << std::endl;
    }
};

// 具体访问者类:权限检查
class PermissionCheckVisitor : public DatabaseOperationVisitor {
public:
    void visit(InsertOperation& operation) override {
        std::cout << "Checking permissions for Insert operation on table " << operation.getTable() << std::endl;
    }

    void visit(UpdateOperation& operation) override {
        std::cout << "Checking permissions for Update operation on table " << operation.getTable() << std::endl;
    }
};

// InsertOperation 和 UpdateOperation 的 accept 方法实现
void InsertOperation::accept(DatabaseOperationVisitor& visitor) {
    visitor.visit(*this);
}

void UpdateOperation::accept(DatabaseOperationVisitor& visitor) {
    visitor.visit(*this);
}

// 客户端代码
int main() {
    std::vector<std::shared_ptr<DatabaseOperation>> operations;
    operations.push_back(std::make_shared<InsertOperation>("users", "{name: 'John', age: 30}"));
    operations.push_back(std::make_shared<UpdateOperation>("users", "{name: 'John', age: 31}"));

    // 日志记录
    LoggingVisitor loggingVisitor;
    for (auto& operation : operations) {
        operation->accept(loggingVisitor);
    }

    // 权限检查
    PermissionCheckVisitor permissionCheckVisitor;
    for (auto& operation : operations) {
        operation->accept(permissionCheckVisitor);
    }

    return 0;
}

总结

访问者模式使得我们可以在不修改元素类的情况下扩展新的操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉夢志昂丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值