Computer Science Design Patterns/Visitor
From Wikibooks, the open-content textbooks collection
< Computer Science Design Patterns(Redirected from Computer Science/Design Patterns/Visitor)
Contents |
[edit] Example in Java
The following example is in the Java programming language:
interface CarElementVisitor { void visit(Wheel wheel); void visit(Engine engine); void visit(Body body); void visitCar(Car car); } interface CarElement { void accept(CarElementVisitor visitor); // CarElements have to provide accept(). } class Wheel implements CarElement { private String name; Wheel(String name) { this.name = name; } String getName() { return this.name; } public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Engine implements CarElement { public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Body implements CarElement { public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Car { CarElement[] elements; public CarElement[] getElements() { return elements.clone(); // Return a copy of the array of references. } public Car() { this.elements = new CarElement[] { new Wheel("front left"), new Wheel("front right"), new Wheel("back left") , new Wheel("back right"), new Body(), new Engine() }; } } class CarElementPrintVisitor implements CarElementVisitor { public void visit(Wheel wheel) { System.out.println("Visiting "+ wheel.getName() + " wheel"); } public void visit(Engine engine) { System.out.println("Visiting engine"); } public void visit(Body body) { System.out.println("Visiting body"); } public void visitCar(Car car) { System.out.println("\nVisiting car"); for(CarElement element : car.getElements()) { element.accept(this); } System.out.println("Visited car"); } } class CarElementDoVisitor implements CarElementVisitor { public void visit(Wheel wheel) { System.out.println("Kicking my "+ wheel.getName()); } public void visit(Engine engine) { System.out.println("Starting my engine"); } public void visit(Body body) { System.out.println("Moving my body"); } public void visitCar(Car car) { System.out.println("\nStarting my car"); for(CarElement carElement : car.getElements()) { carElement.accept(this); } System.out.println("Started car"); } } public class VisitorDemo { static public void main(String[] args){ Car car = new Car(); CarElementVisitor printVisitor = new CarElementPrintVisitor(); CarElementVisitor doVisitor = new CarElementDoVisitor(); printVisitor.visitCar(car); doVisitor.visitCar(car); } }
[edit] Example in D
The following example is in the D programming language:
import std.stdio; import std.string; interface CarElementVisitor { void visit(Wheel wheel); void visit(Engine engine); void visit(Body bod); void visitCar(Car car); } interface CarElement{ void accept(CarElementVisitor visitor); } class Wheel : CarElement { private string name; this(string name) { this.name = name; } string getName() { return name; } public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Engine : CarElement { public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Body : CarElement { public void accept(CarElementVisitor visitor) { visitor.visit(this); } } class Car { CarElement[] elements; public CarElement[] getElements(){ return elements; } public this() { elements = [ cast(CarElement) new Wheel("front left"), cast(CarElement) new Wheel("front right"), cast(CarElement) new Wheel("back left"), cast(CarElement) new Wheel("back right"), cast(CarElement) new Body(), cast(CarElement) new Engine() ]; } } class CarElementPrintVisitor : CarElementVisitor { public void visit(Wheel wheel) { writefln("Visiting "~ wheel.name ~ " wheel"); } public void visit(Engine engine) { writefln("Visiting engine"); } public void visit(Body bod) { writefln("Visiting body"); } public void visitCar(Car car) { writefln("\nVisiting car"); foreach(CarElement element ; car.elements) { element.accept(this); } writefln("Visited car"); } } class CarElementDoVisitor : CarElementVisitor { public void visit(Wheel wheel) { writefln("Kicking my "~ wheel.name); } public void visit(Engine engine) { writefln("Starting my engine"); } public void visit(Body bod) { writefln("Moving my body"); } public void visitCar(Car car) { writefln("\nStarting my car"); foreach(CarElement carElement ; car.getElements()) { carElement.accept(this); } writefln("Started car"); } } void main(){ Car car = new Car; CarElementVisitor printVisitor = new CarElementPrintVisitor; CarElementVisitor doVisitor = new CarElementDoVisitor; printVisitor.visitCar(car); doVisitor.visitCar(car); }
[edit] Example in C++
The following example is an example in the C++ programming language:
#include <string> #include <iostream> #include <vector> using namespace std; class Wheel; class Engine; class Body; class Car; // interface to all car 'parts' struct CarElementVisitor { 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 part struct CarElement { virtual void accept(const CarElementVisitor& visitor) = 0; virtual ~CarElement() {} }; // wheel element, there are four wheels with unique names class Wheel : public CarElement { public: explicit Wheel(const string& name) : name_(name) { } const string& getName() const { return name_; } void accept(const CarElementVisitor& visitor) { visitor.visit(*this); } private: string name_; }; // engine class Engine : public CarElement { public: void accept(const CarElementVisitor& visitor) { visitor.visit(*this); } }; // body class Body : public CarElement { public: void accept(const CarElementVisitor& visitor) { visitor.visit(*this); } }; // car, all car elements(parts) together 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() { for(vector<CarElement*>::iterator it = elements_.begin(); it != elements_.end(); ++it) { delete *it; } } private: vector<CarElement*> elements_; }; // PrintVisitor and DoVisitor show by using a different implementation the Car class is unchanged // even though the algorithm is different in PrintVisitor and DoVisitor. class CarElementPrintVisitor : public CarElementVisitor { public: void visit(Wheel& wheel) const { cout << "Visiting " << wheel.getName() << " wheel" << endl; } void visit(Engine& engine) const { cout << "Visiting engine" << endl; } void visit(Body& body) const { cout << "Visiting body" << endl; } void visitCar(Car& car) const { cout << endl << "Visiting car" << endl; vector<CarElement*>& elems = car.getElements(); for(vector<CarElement*>::iterator it = elems.begin(); it != elems.end(); ++it ) { (*it)->accept(*this); // this issues the callback i.e. to this from the element } cout << "Visited car" << endl; } }; class CarElementDoVisitor : public CarElementVisitor { public: // these are specific implementations added to the original object without modifying the original struct void visit(Wheel& wheel) const { cout << "Kicking my " << wheel.getName() << " wheel" << endl; } void visit(Engine& engine) const { cout << "Starting my engine" << endl; } void visit(Body& body) const { cout << "Moving my body" << endl; } void visitCar(Car& car) const { cout << endl << "Starting my car" << endl; vector<CarElement*>& elems = car.getElements(); for(vector<CarElement*>::iterator it = elems.begin(); it != elems.end(); ++it ) { (*it)->accept(*this); // this issues the callback i.e. to this from the element } cout << "Stopped car" << endl; } }; int main() { Car car; CarElementPrintVisitor printVisitor; CarElementDoVisitor doVisitor; printVisitor.visitCar(car); doVisitor.visitCar(car); return 0; }
[edit] Example in C#
The following example is an example in the C# programming language:
using System; namespace VistorPattern { class Program { static void Main(string[] args) { var car = new Car(); CarElementVisitor printVisitor = new CarElementPrintVisitor(); CarElementVisitor doVisitor = new CarElementDoVisitor(); printVisitor.visitCar(car); doVisitor.visitCar(car); } } public interface CarElementVisitor { void visit(Wheel wheel); void visit(Engine engine); void visit(Body body); void visitCar(Car car); } public interface CarElement { void accept(CarElementVisitor visitor); // CarElements have to provide accept(). } public class Wheel : CarElement { public String name { get; set; } public void accept(CarElementVisitor visitor) { visitor.visit(this); } } public class Engine : CarElement { public void accept(CarElementVisitor visitor) { visitor.visit(this); } } public class Body : CarElement { public void accept(CarElementVisitor visitor) { visitor.visit(this); } } public class Car { public CarElement[] elements { get; private set; } public Car() { elements = new CarElement[] { new Wheel{name = "front left"}, new Wheel{name = "front right"}, new Wheel{name = "back left"} , new Wheel{name="back right"}, new Body(), new Engine() }; } } public class CarElementPrintVisitor : CarElementVisitor { public void visit(Wheel wheel) { Console.WriteLine("Visiting " + wheel.name + " wheel"); } public void visit(Engine engine) { Console.WriteLine("Visiting engine"); } public void visit(Body body) { Console.WriteLine("Visiting body"); } public void visitCar(Car car) { Console.WriteLine("\nVisiting car"); foreach (var element in car.elements) { element.accept(this); } Console.WriteLine("Visited car"); } } public class CarElementDoVisitor : CarElementVisitor { public void visit(Wheel wheel) { Console.WriteLine("Kicking my " + wheel.name); } public void visit(Engine engine) { Console.WriteLine("Starting my engine"); } public void visit(Body body) { Console.WriteLine("Moving my body"); } public void visitCar(Car car) { Console.WriteLine("\nStarting my car"); foreach (var element in car.elements) { element.accept(this); } } } }