Padrões de Projeto em C++: Técnicas Avançadas e Exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Padrões de Projeto Avançados em C++: da Teoria às Implementações Complexas

\n\n

Padrões de projeto são soluções comprovadas para problemas típicos que surgem no desenvolvimento de software. Se os padrões básicos (Singleton, Factory, Observer) são familiares a todo desenvolvedor, as técnicas avançadas exigem um profundo entendimento da linguagem C++, seus templates, herança múltipla e metaprogramação. Neste artigo, analisaremos quatro padrões poderosos: Visitor, Strategy, State e CRTP — com exemplos reais de código e explicação de quando aplicá-los.

\n\n

1. Padrão Visitor (Visitante) — extensão de funcionalidade sem alterar classes

\n\n

O padrão Visitor permite adicionar novas operações a uma hierarquia de classes sem modificar as próprias classes. Isso é especialmente útil quando você tem uma estrutura de objetos estável, mas algoritmos de processamento que mudam com frequência.

\n\n

Exemplo: processamento de formas geométricas

\n\n
#include <iostream>\n#include <vector>\n#include <memory>\n\n// Forward declaration\nclass Circle;\nclass Rectangle;\n\n// Visitante abstrato\nclass Visitor {\npublic:\n    virtual void visit(Circle& circle) = 0;\n    virtual void visit(Rectangle& rectangle) = 0;\n    virtual ~Visitor() = default;\n};\n\n// Elemento abstrato\nclass Shape {\npublic:\n    virtual void accept(Visitor& visitor) = 0;\n    virtual ~Shape() = default;\n};\n\n// Elementos concretos\nclass Circle : public Shape {\npublic:\n    double radius;\n    explicit Circle(double r) : radius(r) {}\n    void accept(Visitor& visitor) override {\n        visitor.visit(*this);\n    }\n};\n\nclass Rectangle : public Shape {\npublic:\n    double width, height;\n    Rectangle(double w, double h) : width(w), height(h) {}\n    void accept(Visitor& visitor) override {\n        visitor.visit(*this);\n    }\n};\n\n// Visitante concreto — cálculo de área\nclass AreaVisitor : public Visitor {\npublic:\n    double totalArea = 0.0;\n    void visit(Circle& circle) override {\n        totalArea += 3.14159 * circle.radius * circle.radius;\n    }\n    void visit(Rectangle& rectangle) override {\n        totalArea += rectangle.width * rectangle.height;\n    }\n};\n\nint main() {\n    std::vector<std::unique_ptr<Shape>> shapes;\n    shapes.push_back(std::make_unique<Circle>(5.0));\n    shapes.push_back(std::make_unique<Rectangle>(4.0, 6.0));\n\n    AreaVisitor areaCalc;\n    for (auto& shape : shapes) {\n        shape->accept(areaCalc);\n    }\n    std::cout << "Total area: " << areaCalc.totalArea << std::endl;\n    return 0;\n}\n
\n\n

Quando usar: quando você precisa executar diferentes operações em objetos de uma hierarquia complexa sem modificar seu código. Desvantagem — adicionar um novo tipo requer alterar todos os visitantes.

\n\n

2. Padrão Strategy (Estratégia) — troca flexível de algoritmos em tempo real

\n\n

Strategy encapsula uma família de algoritmos intercambiáveis e permite substituí-los durante a execução. Em C++, isso é frequentemente implementado via std::function ou classes virtuais.

\n\n

Exemplo: sistema de ordenação de dados

\n\n
#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <memory>\n#include <functional>\n\n// Contexto que usa a estratégia\nclass Sorter {\nprivate:\n    std::function<void(std::vector<int>&)> strategy_;\npublic:\n    explicit Sorter(std::function<void(std::vector<int>&)> strategy)\n        : strategy_(std::move(strategy)) {}\n\n    void setStrategy(std::function<void(std::vector<int>&)> newStrategy) {\n        strategy_ = std::move(newStrategy);\n    }\n\n    void sort(std::vector<int>& data) {\n        if (strategy_) {\n            strategy_(data);\n        }\n    }\n};\n\n// Estratégias concretas\nvoid bubbleSort(std::vector<int>& da                

Blogs

Book Recommendations