In this example, we would want to export a set of geometric shapes into XML. The catch is that we don’t want to change the code of shapes directly or at least keep it to the minimum.
In the end, the Visitor pattern establishes an infrastructure that allows us to add any behaviors to the shapes hierarchy without changing the existing code of those classes.
shapes
shapes/Shape.java: Common shape interface
package refactoring_guru.visitor.example.shapes;
import refactoring_guru.visitor.example.visitor.Visitor;
public interface Shape {
void move(int x, int y);
void draw();
String accept(Visitor visitor);
}
shapes/Dot.java: A dot
package refactoring_guru.visitor.example.shapes;
import refactoring_guru.visitor.example.visitor.Visitor;
public class Dot implements Shape {
private int id;
private int x;
private int y;
public Dot() {
}
public Dot(int id, int x, int y) {
this.id = id;
this.x = x;
this.y = y;
}
@Override
public void move(int x, int y) {
// move shape
}
@Override
public void draw() {
// draw shape
}
@Override
public String accept(Visitor visitor) {
return visitor.visitDot(this);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getId() {
return id;
}
}
shapes/Circle.java: A circle
package refactoring_guru.visitor.example.shapes;
import refactoring_guru.visitor.example.visitor.Visitor;
public class Circle extends Dot {
private int radius;
public Circle(int id, int x, int y, int radius) {
super(id, x, y);
this.radius = radius;
}
@Override
public String accept(Visitor visitor) {
return visitor.visitCircle(this);
}
public int getRadius() {
return radius;
}
}
shapes/Rectangle.java: A rectangle
package refactoring_guru.visitor.example.shapes;
import refactoring_guru.visitor.example.visitor.Visitor;
public class Rectangle implements Shape {
private int id;
private int x;
private int y;
private int width;
private int height;
public Rectangle(int id, int x, int y, int width, int height) {
this.id = id;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
@Override
public String accept(Visitor visitor) {
return visitor.visitRectangle(this);
}
@Override
public void move(int x, int y) {
// move shape
}
@Override
public void draw() {
// draw shape
}
public int getId() {
return id;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
shapes/CompoundShape.java: A compound shape
package refactoring_guru.visitor.example.shapes;
import refactoring_guru.visitor.example.visitor.Visitor;
import java.util.ArrayList;
import java.util.List;
public class CompoundShape implements Shape {
public int id;
public List<Shape> children = new ArrayList<>();
public CompoundShape(int id) {
this.id = id;
}
@Override
public void move(int x, int y) {
// move shape
}
@Override
public void draw() {
// draw shape
}
public int getId() {
return id;
}
@Override
public String accept(Visitor visitor) {
return visitor.visitCompoundGraphic(this);
}
public void add(Shape shape) {
children.add(shape);
}
}