Visitor

Motivation

In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures. It is one way to easily follow the open/closed principle.

Collections are data types widely used in object oriented programming. Often collections contain objects of different types and in those cases some operations have to be performed on all the collection elements without knowing the type.

A possible approach to apply a specific operation on objects of different types in a collection would be the use if blocks in conjunction with 'instanceof' for each element. This approach is not a nice one, not flexible and not object oriented at all. At this point we should think to the Open Close principle and we should remember from there that we can replace if blocks with an abstract class and each concrete class will implement its own operation.


Intent

  • Represents an operation to be performed on the elements of an object structure.
  • Visitor lets you define a new operation without changing the classes of the elements on which it operates.
See more details - Click Here
-------------------------------------------------------------------
public class Visitorpattern {
 static public void main(String[] args) {
  Car car = new Car();
  car.accept(new CarElementPrintVisitor());
  car.accept(new CarElementDoVisitor());
 }

}

interface CarElementVisitor {
 void visit(Wheel wheel);

 void visit(Engine engine);
 void visit(Body body);
 void visit(Car car);
}


interface CarElement {
 void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}


class Wheel implements CarElement {
 private String name;

 public Wheel(String name) {
  this.name = name;
 }

 public 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 implements CarElement {
 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() };
 }

 public void accept(CarElementVisitor visitor) {
  for (CarElement element : this.getElements())
  {
   element.accept(visitor);
  }
  visitor.visit(this);
 }
}


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 visit(Car car) {
  System.out.println("Visiting car");
 }
}


class CarElementDoVisitor implements CarElementVisitor {
 public void visit(Wheel wheel) {
  System.out.println("Kicking my " + wheel.getName() + " wheel");
 }

 public void visit(Engine engine) {
  System.out.println("Starting my engine");
 }

 public void visit(Body body) {
  System.out.println("Moving my body");
 }

 public void visit(Car car) {
  System.out.println("Starting my car");
 }
}