《C++20设计模式》访问者模式

一、前言

1、如何学好访问者模式,前提条件肯定是要知道访问者模式是干什么的

扩展原有类族的功能(形象点来说就是系统升级),符合开闭原则,对一类代码都进行扩展

2、访问者模式实现方式

这里介绍两种,为什么是两种而不是一种呢?因为真的各有各的优点,很难取舍!🫠

  • 经典访问者模式
  • 使用std::variant和std::visit的实现访问者模式

相关代码可以在这里,如有帮助给个star!AidenYuanDev/design_patterns_in_modern_Cpp_20

二、经典访问者模式

类族每个类都添加accept()函数,传入自身this,调用访问者,然后经由访问者实现新功能。

1、UML类图

经典访问者模式

2、实现

#include <iostream>
#include <memory>
using namespace std;

class Cpu;
class Memory;

class Visitor {
public:
    virtual void visit_cpu(const Cpu& cpu) const = 0;
    virtual void visit_memory(const Memory& memory) const = 0;
};

class Computer {
public:
    virtual void accept(const Visitor& visitor) const = 0;
    virtual void show() const = 0;
};

class Cpu : public Computer {
public:
    void accept(const Visitor& visitor) const override {
        visitor.visit_cpu(*this);
    }
    void show() const override {
        cout << "老旧Cpu";
    }
};

class Memory : public Computer {
public:
    void accept(const Visitor& visitor) const override {
        visitor.visit_memory(*this);
    }
    void show() const override {
        cout << "老旧Memory";
    }

};

class Visitor_Rog : public Visitor {
public:
    void visit_cpu(const Cpu& cpu) const override {
        cpu.show();   
        cout << "升级为新Rog Cpu" << endl;
    }
    void visit_memory(const Memory& memory) const override {
        memory.show();
        cout << "升级为Rog Memory" << endl;
    }
};

int main(){
    auto cpu = make_unique<Cpu>();
    auto memory = make_unique<Memory>();
    auto visitor_rog = make_unique<Visitor_Rog>();

    cpu->accept(*visitor_rog);
    memory->accept(*visitor_rog);
    return 0;
}

三、使用std::variant和std::visit的实现访问者模式

这种方法利用了 C++17 引入的新特性,可以在某些情况下提供更简洁和高效的实现。所以如果可以支持C++17那么我还是推荐用这个(因为真的简单和方便)

1、UML类图

variant实现访问者模式

2、实现


#include <iostream>
#include <vector>
#include <variant>
#include <string>

// 定义元素类型
class Circle {
public:
    void draw() const { std::cout << "Drawing a circle\n"; }
};

class Square {
public:
    void draw() const { std::cout << "Drawing a square\n"; }
};

class Triangle {
public:
    void draw() const { std::cout << "Drawing a triangle\n"; }
};

// 使用 std::variant 定义可能的元素类型
using Shape = std::variant<Circle, Square, Triangle>;

// 定义访问者
class DrawVisitor {
public:
    void operator()(const Circle& c) const { c.draw(); }
    void operator()(const Square& s) const { s.draw(); }
    void operator()(const Triangle& t) const { t.draw(); }
};

class AreaVisitor {
public:
    double operator()(const Circle&) const { 
        std::cout << "Calculating circle area\n";
        return 3.14; // 简化计算
    }
    double operator()(const Square&) const { 
        std::cout << "Calculating square area\n";
        return 4.0; // 简化计算
    }
    double operator()(const Triangle&) const { 
        std::cout << "Calculating triangle area\n";
        return 1.5; // 简化计算
    }
};

// 使用示例
int main() {
    std::vector<Shape> shapes = {Circle(), Square(), Triangle()};

    // 使用 DrawVisitor
    std::cout << "Drawing shapes:\n";
    for (const auto& shape : shapes) {
        std::visit(DrawVisitor(), shape);
    }

    // 使用 AreaVisitor
    std::cout << "\nCalculating areas:\n";
    for (const auto& shape : shapes) {
        double area = std::visit(AreaVisitor(), shape);
        std::cout << "Area: " << area << "\n";
    }

    return 0;
}

相关推荐

  1. C++设计模式访问模式

    2024-07-11 13:16:03       33 阅读
  2. C++ QT设计模式访问模式

    2024-07-11 13:16:03       26 阅读
  3. C++新经典设计模式》之第20访问模式

    2024-07-11 13:16:03       41 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 13:16:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 13:16:03       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 13:16:03       58 阅读
  4. Python语言-面向对象

    2024-07-11 13:16:03       69 阅读

热门阅读

  1. 达梦数据库系列—23. DSC集群搭建

    2024-07-11 13:16:03       17 阅读
  2. RabbitMQ 迁移

    2024-07-11 13:16:03       21 阅读
  3. 【编程范式】理解响应式编程(reactive programming)

    2024-07-11 13:16:03       26 阅读
  4. Python 循环语句

    2024-07-11 13:16:03       21 阅读
  5. 【EasyExcel】动态替换表头内容并应用样式

    2024-07-11 13:16:03       21 阅读
  6. IPython的使用技巧整理

    2024-07-11 13:16:03       23 阅读
  7. uniapp踩坑小伎俩记录

    2024-07-11 13:16:03       22 阅读
  8. anaconda新建虚拟环境并同步至jupyter

    2024-07-11 13:16:03       20 阅读