Skip to content

Instantly share code, notes, and snippets.

@adam-singer
Created June 26, 2012 03:41
Show Gist options
  • Save adam-singer/2993134 to your computer and use it in GitHub Desktop.
Save adam-singer/2993134 to your computer and use it in GitHub Desktop.
Basic Visitor Pattern Example
// Reference: http://en.wikipedia.org/wiki/Visitor_pattern
interface CarElementVisitor {
void visitWheel(Wheel wheel);
void visitEngine(Engine engine);
void visitBody(Body body);
void visitCar(Car car);
}
interface CarElement {
void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}
class Wheel implements CarElement {
String name;
Wheel(String name) {
this.name = name;
}
void accept(CarElementVisitor visitor) {
/*
* Wheel.accept(CarElementVisitor) overrides CarElement.accept(CarElementVisitor), so the call
* to accept is bound at run time. This can be considered the first dispatch.
* The decision to call CarElementVisitor.visitWheel(Wheel) however, rather than the other 'visit'
* methods in CarElementVisitor, can be made during compile time since 'this' is known at compile
* time to be a Wheel. Moreover, each subclass of CarElementVisitor overrides the visitWheel(Wheel),
* which is another decision that is made at run time. This can be considered the second dispatch.
*/
visitor.visitWheel(this);
}
}
class Engine implements CarElement {
void accept(CarElementVisitor visitor) {
visitor.visitEngine(this);
}
}
class Body implements CarElement {
void accept(CarElementVisitor visitor) {
visitor.visitBody(this);
}
}
class Car implements CarElement {
List<CarElement> elements;
Car() {
//create new Array of elements
this.elements = new List<CarElement>();
this.elements.add(new Wheel("front left"));
this.elements.add(new Wheel("front right"));
this.elements.add(new Wheel("back left"));
this.elements.add(new Wheel("back right"));
this.elements.add(new Body());
this.elements.add(new Engine());
}
void accept(CarElementVisitor visitor) {
for(CarElement elem in elements) {
elem.accept(visitor);
}
visitor.visitCar(this);
}
}
class CarElementPrintVisitor implements CarElementVisitor {
void visitWheel(Wheel wheel) {
print("Visiting ${wheel.name} wheel");
}
void visitEngine(Engine engine) {
print("Visiting engine");
}
void visitBody(Body body) {
print("Visiting body");
}
void visitCar(Car car) {
print("Visiting car");
}
}
class CarElementDoVisitor implements CarElementVisitor {
void visitWheel(Wheel wheel) {
print("Kicking my ${wheel.name} wheel");
}
void visitEngine(Engine engine) {
print("Starting my engine");
}
void visitBody(Body body) {
print("Moving my body");
}
void visitCar(Car car) {
print("Starting my car");
}
}
void main() {
Car car = new Car();
car.accept(new CarElementPrintVisitor());
car.accept(new CarElementDoVisitor());
}
@atebitftw
Copy link

I see the Dart engy's using this pattern a lot in their parsing code.

@adam-singer
Copy link
Author

I know, its definitely a used pattern in dart2js. Might start to gather what common design patterns look like in dart, maybe something similar to dofactories (www.dofactory.com) code but for dart.

@atebitftw
Copy link

That's a great idea. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment