From 8177d4c19154851d613ed8b2e8309f9981a03878 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Tue, 11 May 2021 20:56:05 -0400 Subject: [PATCH] Add example of visitor pattern in C++ --- cpp/patterns/CMakeLists.txt | 1 + cpp/patterns/visitor/CMakeLists.txt | 20 +++++++++ cpp/patterns/visitor/main.cpp | 16 ++++++++ cpp/patterns/visitor/visitor.cpp | 32 +++++++++++++++ cpp/patterns/visitor/visitor.hpp | 63 +++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 cpp/patterns/visitor/CMakeLists.txt create mode 100644 cpp/patterns/visitor/main.cpp create mode 100644 cpp/patterns/visitor/visitor.cpp create mode 100644 cpp/patterns/visitor/visitor.hpp diff --git a/cpp/patterns/CMakeLists.txt b/cpp/patterns/CMakeLists.txt index 49b3e4e..3eb2aae 100644 --- a/cpp/patterns/CMakeLists.txt +++ b/cpp/patterns/CMakeLists.txt @@ -23,3 +23,4 @@ add_subdirectory(prototype) add_subdirectory(abstract-factory) add_subdirectory(state) add_subdirectory(observer) +add_subdirectory(visitor) diff --git a/cpp/patterns/visitor/CMakeLists.txt b/cpp/patterns/visitor/CMakeLists.txt new file mode 100644 index 0000000..ccb6067 --- /dev/null +++ b/cpp/patterns/visitor/CMakeLists.txt @@ -0,0 +1,20 @@ +############################################################################### +## Author: Shaun Reed ## +## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## About: A project for practicing the visitor C++ design pattern ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +############################################################################## +# +cmake_minimum_required(VERSION 3.15) +project( + #[[NAME]] Visitor + VERSION 1.0 + DESCRIPTION "An example of the visitor design pattern in C++" + LANGUAGES CXX +) +add_compile_options("-Wall") + +add_library(visitor "visitor.cpp") +add_executable(visitor-test "main.cpp") +target_link_libraries(visitor-test visitor) diff --git a/cpp/patterns/visitor/main.cpp b/cpp/patterns/visitor/main.cpp new file mode 100644 index 0000000..fe133e4 --- /dev/null +++ b/cpp/patterns/visitor/main.cpp @@ -0,0 +1,16 @@ + +#include + +#include "visitor.hpp" + +int main(const int argc, const char * argv[]) +{ + Gear *newGear = new Gear(1.5f, 1.0f); + PartVisitor *newVisitor = new PartVisitor; + // Test visiting the Gear concrete component with PartVisitor + newGear->accept(newVisitor); + + // Testing a Spring concrete component on the same visitor + auto *newSpring = new Spring(2.5f, 5.0f); + newSpring->accept(newVisitor); +} diff --git a/cpp/patterns/visitor/visitor.cpp b/cpp/patterns/visitor/visitor.cpp new file mode 100644 index 0000000..1665488 --- /dev/null +++ b/cpp/patterns/visitor/visitor.cpp @@ -0,0 +1,32 @@ + +#include "visitor.hpp" + + +/******************************************************************************/ +// Concrete components + +void Gear::accept(PartVisitor *v) +{ + v->visit(this); +} + +void Spring::accept(PartVisitor *v) +{ + v->visit(this); +} + + +/******************************************************************************/ +// Concrete visitors + +void PartVisitor::visit(Gear *g) +{ + std::cout << g->getName() << " is price " << g->getPrice() << " with radius of " + << g->getRadius() << std::endl; +} + +void PartVisitor::visit(Spring *g) +{ + std::cout << g->getName() << " is price " << g->getPrice() + << " with elasticity of " << g->getElasticity() << std::endl; +} diff --git a/cpp/patterns/visitor/visitor.hpp b/cpp/patterns/visitor/visitor.hpp new file mode 100644 index 0000000..886be69 --- /dev/null +++ b/cpp/patterns/visitor/visitor.hpp @@ -0,0 +1,63 @@ + +#ifndef VISITOR_HPP +#define VISITOR_HPP + +#include +#include +#include + +class PartVisitor; + +// Abstract component +class Part { +public: + Part(std::string name_, const float &price_) : + name(std::move(name_)), price(price_) {} + + inline std::string getName() const { return name;} + inline float getPrice() const { return price;} + + virtual void accept(PartVisitor *v) = 0; +private: + std::string name; + float price; +}; + + +/******************************************************************************/ +// Concrete components +class Gear : public Part { +public: + Gear(const float &price_, const float &radius_) : + Part("Gear", price_), radius(radius_) {} + + void accept(PartVisitor *v) override; + inline float getRadius() const { return radius;} + +private: + float radius; +}; + +class Spring : public Part { +public: + Spring(const float &price_, const float &elasticity_) : + Part("Spring", price_), elasticity(elasticity_) {} + + void accept(PartVisitor *v) override; + inline float getElasticity() const { return elasticity;} + +private: + float elasticity; +}; + + +/******************************************************************************/ +// Concrete visitors +class PartVisitor { +public: + // Handle visiting different components accordingly + virtual void visit(Gear *g); + virtual void visit(Spring *g); +}; + +#endif // VISITOR_HPP