From 4cd1459a7e8008f223fd83c9f1e796267978a496 Mon Sep 17 00:00:00 2001 From: Jakub Vojvoda Date: Sat, 1 Oct 2016 20:05:23 +0200 Subject: [PATCH] add Visitor pattern --- visitor/README.md | 15 +++++++ visitor/Visitor.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 visitor/README.md create mode 100644 visitor/Visitor.cpp diff --git a/visitor/README.md b/visitor/README.md new file mode 100644 index 0000000..ff94786 --- /dev/null +++ b/visitor/README.md @@ -0,0 +1,15 @@ +## Visitor + +Visitor represents an operation to be performed on the elements of an object +structure. It lets you define a new operation without changing the classes of +the elements on which it operates. The pattern has behavioral purpose and applies +to the objects. + +### When to use + +* an object structure contains many classes of objects with differing interfaces, +and you want to perform operations on these objects that depend on their concrete classes +* many distinct and unrelated operations need to be performed on objects in an object structure, +and you want to avoid "polluting" their classes with these operations +* the classes defining the object structure rarely change, but you often want +to define new operations over the structure \ No newline at end of file diff --git a/visitor/Visitor.cpp b/visitor/Visitor.cpp new file mode 100644 index 0000000..67a290f --- /dev/null +++ b/visitor/Visitor.cpp @@ -0,0 +1,99 @@ +/* + * C++ Design Patterns: Visitor + * Author: Jakub Vojvoda [github.com/JakubVojvoda] + * 2016 + * + * Source code is licensed under MIT License + * (for more details see LICENSE) + * + */ + +#include + +class Element; +class ConcreteElementA; +class ConcreteElementB; + +/* + * Visitor + * declares a Visit operation for each class of ConcreteElement + * in the object structure + */ +class Visitor { +public: + virtual void visitElementA(ConcreteElementA *element) = 0; + virtual void visitElementB(ConcreteElementB *element) = 0; +}; + +/* + * Concrete Visitors + * implement each operation declared by Visitor, which implement + * a fragment of the algorithm defined for the corresponding class + * of object in the structure + */ +class ConcreteVisitor1 : public Visitor { +public: + void visitElementA(ConcreteElementA *) { + std::cout << "Concrete Visitor 1: Element A visited." << std::endl; + } + + void visitElementB(ConcreteElementB *) { + std::cout << "Concrete Visitor 1: Element B visited." << std::endl; + } +}; + +class ConcreteVisitor2 : public Visitor { +public: + void visitElementA(ConcreteElementA *) { + std::cout << "Concrete Visitor 2: Element A visited." << std::endl; + } + + void visitElementB(ConcreteElementB *) { + std::cout << "Concrete Visitor 2: Element B visited." << std::endl; + } +}; + +/* + * Element + * defines an accept operation that takes a visitor as an argument + */ +class Element { +public: + virtual void accept(Visitor &visitor) = 0; +}; + +/* + * Concrete Elements + * implement an accept operation that takes a visitor as an argument + */ +class ConcreteElementA : public Element { +public: + void accept(Visitor &visitor) { + visitor.visitElementA(this); + } +}; + +class ConcreteElementB : public Element { +public: + void accept(Visitor &visitor) { + visitor.visitElementB(this); + } +}; + + +int main() +{ + ConcreteElementA elementA; + ConcreteElementB elementB; + + ConcreteVisitor1 visitor1; + ConcreteVisitor2 visitor2; + + elementA.accept(visitor1); + elementA.accept(visitor2); + + elementB.accept(visitor1); + elementB.accept(visitor2); + + return 0; +}