C++设计模式:高级技巧与代码示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++ 高级设计模式:从理论到实际代码



设计模式是面向对象编程中经过验证的典型问题解决方案。如果你已经掌握了基础模式(Singleton、Factory、Observer),是时候进入下一个层次了。本文将深入讲解四种高级设计模式:Visitor(访问者)、Strategy(策略)、State(状态)和Command(命令)。所有示例均使用现代 C++17/20 编写,包含智能指针、多态和模板。



1. Visitor(访问者)模式



Visitor 模式允许在不修改现有类的情况下,向类层次结构添加新操作。这是处理 AST 树、图形场景或导出系统的理想解决方案。



问题

你有一个几何图形类层次结构(Circle、Rectangle、Triangle)。需要实现以下操作:计算面积、绘制、序列化为 JSON。如果在每个类中添加方法,会违反开闭原则。



C++17 解决方案

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

// 前向声明class Circle;class Rectangle;

class Visitor {public: virtual void visit(Circle& c) = 0; virtual void visit(Rectangle& r) = 0; virtual ~Visitor() = default;};

class Shape {public: virtual void accept(Visitor& v) = 0; virtual ~Shape() = default;};

class Circle : public Shape {public: double radius = 5.0; void accept(Visitor& v) override { v.visit(*this); }};

class Rectangle : public Shape {public: double width = 4.0, height = 6.0; void accept(Visitor& v) override { v.visit(*this); }};

// 具体访问者class AreaVisitor : public Visitor {public: void visit(Circle& c) override { std::cout << "Circle area: " << 3.14159 * c.radius * c.radius << ""; } void visit(Rectangle& r) override { std::cout << "Rectangle area: " << r.width * r.height << ""; }};

int main() { std::vector<std::unique_ptr<Shape>> shapes; shapes.push_back(std::make_unique<Circle>()); shapes.push_back(std::make_unique<Rectangle>());

AreaVisitor av; for (auto& s : shapes) { s->accept(av); } return 0;}


2. Strategy(策略)模式



Strategy 允许在运行时更改数据处理算法。与处理对象层次结构的 Visitor 不同,Strategy 封装了单个算法。



实际场景

文件压缩系统。用户选择算法:ZIP、GZIP 或自定义算法。使用 Strategy 替代 if-else 链。



使用 std::function 的实现

#include <iostream>#include <functional>#include <string>

class CompressionContext {private: std::function<void(const std::string&)> strategy_;public: explicit CompressionContext(std::function<void(const std::string&)> strategy) : strategy_(std::move(strategy)) {}

void setStrategy(std::function<void(const std::string&)> strategy) { strategy_ = std::move(strategy); }

void compress(const std::string& data) { if (strategy_) { strategy_(data); } else { std::cout << "No strategy set"; } }};

int main() { auto zip = [](const std::string& d) { std::cout << "Compressing with ZIP: " << d << ""; }; auto gzip = [](const std::string& d) { std::cout << "Compressing with GZIP: " << d << ""; };

CompressionContext ctx(zip); ctx.compress("Hello World"); // ZIP

ctx.setStrategy(gzip)

博客

书籍推荐