// A simple class hierarchy that uses the visitor to add functionality.
//
class VehicleVisitor;
class Vehicle
{
public:
// To implement the visitor pattern
// The class simply needs to implement the accept method
// That takes a reference to a visitor object that provides
// new functionality.
virtual void accept(VehicleVisitor& visitor) = 0
};
class Plane: public Vehicle
{
public:
// Each concrete representation simply calls the visit()
// method on the visitor object passing itself as the parameter.
virtual void accept(VehicleVisitor& visitor) {visitor.visit(*this);}
void fly(std::string const& destination);
};
class Train: public Vehicle
{
public:
virtual void accept(VehicleVisitor& visitor) {visitor.visit(*this);}
void locomote(std::string const& destination);
};
class Automobile: public Vehicle
{
public:
virtual void accept(VehicleVisitor& visitor) {visitor.visit(*this);}
void drive(std::string const& destination);
};
class VehicleVisitor
{
public:
// The visitor interface implements one method for each class in the
// hierarchy. When implementing new functionality you just create the
// functionality required for each type in the appropriate method.
virtual void visit(Plane& object) = 0;
virtual void visit(Train& object) = 0;
virtual void visit(Automobile& object) = 0;
// Note: because each class in the hierarchy needs a virtual method
// in visitor base class this makes extending the hierarchy ones defined
// hard.
};
An example usage:
// Add the functionality `Move` to an object via a visitor.
class MoveVehicleVisitor
{
std::string const& destination;
public:
MoveVehicleVisitor(std::string const& destination)
: destination(destination)
{}
virtual void visit(Plane& object) {object.fly(destination);}
virtual void visit(Train& object) {object.locomote(destination);}
virtual void visit(Automobile& object) {object.drive(destination);}
};
int main()
{
MoveVehicleVisitor moveToDenver("Denver");
Vehicle& object = getObjectToMove();
object.accept(moveToDenver);
}