Created
February 28, 2021 20:11
-
-
Save FONQRI/3631f96c6616800abcd22604f4b2be25 to your computer and use it in GitHub Desktop.
Simple Example for data export with visitor Design pattern
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NormalPoint; | |
class LoiterPoint; | |
class ExporterInterface | |
{ | |
public: | |
virtual void exportNormalPoint(const NormalPoint* element) const = 0; | |
virtual void exportLoiterPoint(const LoiterPoint* element) const = 0; | |
}; | |
/** | |
* The Component interface declares an `accept` method that should take the base | |
* visitor interface as an argument. | |
*/ | |
class BasePoint | |
{ | |
public: | |
virtual ~BasePoint() | |
{} | |
virtual void exportData(ExporterInterface* visitor) const = 0; | |
}; | |
/** | |
* Each Concrete Component must implement the `Accept` method in such a way that | |
* it calls the visitor's method corresponding to the component's class. | |
*/ | |
class NormalPoint : public BasePoint | |
{ | |
/** | |
* Note that we're calling `visitConcreteComponentA`, which matches the | |
* current class name. This way we let the visitor know the class of the | |
* component it works with. | |
*/ | |
public: | |
void exportData(ExporterInterface* visitor) const override | |
{ | |
visitor->exportNormalPoint(this); | |
} | |
/** | |
* Concrete Components may have special methods that don't exist in their base | |
* class or interface. The Visitor is still able to use these methods since | |
* it's aware of the component's concrete class. | |
*/ | |
std::string ExclusiveMethodOfConcreteComponentA() const | |
{ | |
return "A"; | |
} | |
}; | |
class LoiterPoint : public BasePoint | |
{ | |
/** | |
* Same here: visitConcreteComponentB => ConcreteComponentB | |
*/ | |
public: | |
void exportData(ExporterInterface* visitor) const override | |
{ | |
visitor->exportLoiterPoint(this); | |
} | |
std::string SpecialMethodOfConcreteComponentB() const | |
{ | |
return "B"; | |
} | |
}; | |
/** | |
* Concrete Visitors implement several versions of the same algorithm, which can | |
* work with all concrete component classes. | |
* | |
* You can experience the biggest benefit of the Visitor pattern when using it | |
* with a complex object structure, such as a Composite tree. In this case, it | |
* might be helpful to store some intermediate state of the algorithm while | |
* executing visitor's methods over various objects of the structure. | |
*/ | |
class JsonExporter : public ExporterInterface | |
{ | |
public: | |
void exportNormalPoint(const NormalPoint* element) const override | |
{ | |
std::cout << element->ExclusiveMethodOfConcreteComponentA() << " + ConcreteVisitor1\n"; | |
} | |
void exportLoiterPoint(const LoiterPoint* element) const override | |
{ | |
std::cout << element->SpecialMethodOfConcreteComponentB() << " + ConcreteVisitor1\n"; | |
} | |
}; | |
class XmlExporter : public ExporterInterface | |
{ | |
public: | |
void exportNormalPoint(const NormalPoint* element) const override | |
{ | |
std::cout << element->ExclusiveMethodOfConcreteComponentA() << " + ConcreteVisitor2\n"; | |
} | |
void exportLoiterPoint(const LoiterPoint* element) const override | |
{ | |
std::cout << element->SpecialMethodOfConcreteComponentB() << " + ConcreteVisitor2\n"; | |
} | |
}; | |
/** | |
* The client code can run visitor operations over any set of elements without | |
* figuring out their concrete classes. The accept operation directs a call to | |
* the appropriate operation in the visitor object. | |
*/ | |
void ClientCode(std::array<const BasePoint*, 2> components, ExporterInterface* visitor) | |
{ | |
// ... | |
for (const BasePoint* comp : components) | |
{ | |
comp->exportData(visitor); | |
} | |
// ... | |
} | |
int main() | |
{ | |
std::array<const BasePoint*, 2> components = {new NormalPoint, new LoiterPoint}; | |
std::cout << "The client code works with all visitors via the base Visitor interface:\n"; | |
JsonExporter* visitor1 = new JsonExporter; | |
ClientCode(components, visitor1); | |
std::cout << "\n"; | |
std::cout << "It allows the same client code to work with different types of visitors:\n"; | |
XmlExporter* visitor2 = new XmlExporter; | |
ClientCode(components, visitor2); | |
for (const BasePoint* comp : components) | |
{ | |
delete comp; | |
} | |
delete visitor1; | |
delete visitor2; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment