Behavioral Pattern: Visitor
Download
1 / 11

Behavioral Pattern: Visitor - PowerPoint PPT Presentation


  • 52 Views
  • Uploaded on

Behavioral Pattern: Visitor. Chapter 5 – Page 224. When an algorithm is separated from an object structure upon which it operates, new operations can be added to existing object structures without modifying those structures.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Behavioral Pattern: Visitor' - pier


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

Behavioral Pattern: Visitor

Chapter 5 – Page 224

When an algorithm is separated from an object structure upon which it operates, new operations can be added to existing object structures without modifying those structures

The Visitor Pattern allows new virtual functions to be added to a family of classes without modifying the classes themselves; instead, one creates a visitor class that implements all of the appropriate specializations of the virtual function.

This is particularly useful when there are a large number of instances of a small number of classes and some operation must be performed that involves all or most of them.

(While powerful, the Visitor Pattern is more limited than conventional virtual functions since it isn’t possible to create visitors for objects without adding a small callback method inside each class and the callback method in each of the classes is not inheritable.)


The Visitor Pattern

Chapter 5 – Page 225

  • The Visitor declares a visit operation for each class of ConcreteElement in the object structure. The operation's name and signature identifies the class that sends the Visit request to the visitor. That lets the visitor determine the concrete class of the element being visited. Then the visitor can access the elements directly through its particular interface.

  • The ConcreteVisitor implements each operation declared by the Visitor. Each operation implements a fragment of the algorithm defined for the corresponding class or object in the structure. The ConcreteVisitor provides the context for the algorithm and stores its local state. This state often accumulates results during the traversal of the structure.

  • The Object Structure can enumerate its elements and may provide a high-level interface to allow the visitor to visit its elements. It may either be a Composite (pattern) or a collection such as a list or a set.

  • The Element defines an Accept operation that takes a visitor as an argument, while the ConcreteElement implements an Accept operation that takes a visitor as an argument.


Non-Software Example: Cab-Calling

Chapter 5 – Page 226

When a person calls a taxi company he or she becomes part of the company's list of customers (the ObjectStructure).

The taxi company’s dispatcher (the Client) then sends a cab (the Visitor) to the customer (the Element).

Upon entering the taxi, the customer is no longer in control of his or her own transportation, the taxi (i.e., the taxi driver) is.


Software Example: Car Parts

Chapter 5 – Page 227

The Car (ObjectStructure) is composed of various CarElements (Wheels, Engine, Body).

The CarElementVisitor provides an interface for “visiting” each type of CarElement.

The DiagnosticVisitor and the TestDriveVisitor implement specific algorithms for dealing with the Car’s CarElements without altering the definitions of the Car or the CarElements.


Car Parts Visitor Pattern C++ Code

Chapter 5 – Page 228

#include <string>

#include <iostream>

#include <vector>

using namespace std;

class Wheel;

class Engine;

class Body;

class Car;

// Interface to all car parts

structCarElementVisitor

{

virtual void visit(Wheel& wheel) const = 0;

virtual void visit(Engine& engine) const = 0;

virtual void visit(Body& body) const = 0;

virtual void visitCar(Car& car) const = 0;

virtual ~CarElementVisitor() {}

};

// Interface to one car part

structCarElement

{

virtual void accept(constCarElementVisitor& visitor) = 0;

virtual ~CarElement() {}

};


// Wheel element, there are four wheels with unique names

class Wheel : publicCarElement

{

public:

explicit Wheel(const string& name) : name(name) {}

const string& getName() const

{

return name;

}

void accept(constCarElementVisitor& visitor)

{

visitor.visit(*this);

}

private:

string name;

};

// Engine element

class Engine : publicCarElement

{

public:

void accept(const CarElementVisitor& visitor)

{

visitor.visit(*this);

}

};

// Body element

class Body : publicCarElement

{

public:

void accept(constCarElementVisitor& visitor)

{

visitor.visit(*this);

}

};

Chapter 5 – Page 229


Chapter 5 – Page 230

// Car, all car elements (parts) together in one vector

class Car

{

public:

vector<CarElement*>& getElements()

{

return elements;

}

Car()

{

// assume that neither push_back nor Wheel(const string&) may throw

elements.push_back( new Wheel("front left") );

elements.push_back( new Wheel("front right") );

elements.push_back( new Wheel("back left") );

elements.push_back( new Wheel("back right") );

elements.push_back( new Body() );

elements.push_back( new Engine() );

}

~Car()

{

vector<CarElement*>::iterator it;

for (it = elements.begin(); it != elements.end(); ++it)

{

delete *it;

}

}

private:

vector<CarElement*> elements;

};


Chapter 5 – Page 231

// DiagnosticVisitor adds a diagnostic capability to the

// Car class without modifying the Car class itself.

classCarElementDiagnosticVisitor : publicCarElementVisitor

{

public:

void visit(Wheel& wheel) const

{

cout << "Testing the car's " << wheel.getName()

<< " wheel for tread and punctures" << endl;

}

void visit(Engine& engine) const

{

cout << "Examining the car's engine for leaks and loose belts" << endl;

}

void visit(Body& body) const

{

cout << "Examining the car's body for dents and scratches" << endl;

}

voidvisitCar(Car& car) const

{

cout << "Performing diagnostic testing on the car" << endl;

vector<CarElement*>& elems = car.getElements();

// Cycle through the car's elements, issuing a

// callback from each car element to this visitor.

vector<CarElement*>::iterator it;

for (it = elems.begin(); it != elems.end(); ++it )

{

(*it)->accept(*this);

}

cout << "Diagnostic testing complete" << endl << endl;

}

};


Chapter 5 – Page 232

// TestDriveVisitor adds a test drive capability to the

// Car class without modifying the Car class itself.

classCarElementTestDriveVisitor : publicCarElementVisitor

{

public:

void visit(Wheel& wheel) const

{

cout << "Kicking the car's " << wheel.getName() << " tire" << endl;

}

void visit(Engine& engine) const

{

cout << "Starting the car's engine" << endl;

}

void visit(Body& body) const

{

cout << "Driving the car for a road test" << endl;

}

voidvisitCar(Car& car) const

{

cout << "Test driving the car" << endl;

vector<CarElement*>& elems = car.getElements();

// Cycle through the car's elements, issuing a

// callback from each car element to this visitor.

vector<CarElement*>::iterator it;

for (it = elems.begin(); it != elems.end(); ++it )

{

(*it)->accept(*this);

}

cout << "Test drive complete" << endl << endl;

}

};


Chapter 5 – Page 233

void main()

{

Car car;

CarElementDiagnosticVisitorprintVisitor;

CarElementTestDriveVisitordoVisitor;

printVisitor.visitCar(car);

doVisitor.visitCar(car);

}


Visitor Pattern Advantages

Chapter 5 – Page 234

  • The Visitor Pattern permits the addition of functions to class libraries for which either the source code or the ability to change the source code is unavailable.

  • This pattern is also helpful when it is necessary to obtain data from a disparate collection of unrelated classes and use it to present the results of a global calculation to the user program.

  • It can be used to gather related operations into a single class rather than forcing the designer to change or derive classes to add these operations.


ad