C++中的访问者模式
目录
访问者模式(Visitor Pattern)
实际应用
文件系统的访问者模式
形状绘制系统
数据库操作系统
总结
访问者模式(Visitor Pattern)
访问者模式是一种行为设计模式,它允许你在不修改元素类的前提下,定义作用于这些类上的新的操作。访问者模式将操作的算法与对象结构分离,使得算法可以在不修改对象结构的前提下扩展。
实际应用
文件系统的访问者模式
— 文件系统结构,计算总大小和打印文件结构。
#include
#include
#include
#include
// 前向声明访问者类
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> elements;
public:
Folder(const std::string& name) : name(name) {}
void addElement(const std::shared_ptr& element) {
elements.push_back(element);
}
const std::string& getName() const {
return name;
}
const std::vector<std::shared_ptr>& 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() <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("root");
auto file1 = std::make_shared("file1.txt", 100);
auto file2 = std::make_shared("file2.txt", 200);
auto subFolder = std::make_shared("subfolder");
auto file3 = std::make_shared("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" <accept(structurePrinter);
return 0;
}
形状绘制系统
— 形状绘制系统,计算面积和绘制形状。
#include
#include
#include
#include
// 前向声明访问者类
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> shapes;
shapes.push_back(std::make_shared(5.0));
shapes.push_back(std::make_shared(4.0, 6.0));
// 计算总面积
AreaCalculatorVisitor areaCalculator;
for (auto& shape : shapes) {
shape->accept(areaCalculator);
}
std::cout << "Total area: " << areaCalculator.getTotalArea() <accept(shapeDrawer);
}
return 0;
}
数据库操作系统
— 数据库操作系统,日志记录和权限检查。
#include
#include
#include
#include
// 前向声明访问者类
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> operations;
operations.push_back(std::make_shared("users", "{name: 'John', age: 30}"));
operations.push_back(std::make_shared("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;
}
总结
访问者模式使得我们可以在不修改元素类的情况下扩展新的操作。