I've been going over the Visitor Pattern to try to understand it. Is this a correct implementation of the Visitor Pattern for RPS??
Here's the implementation code:
public enum ResultEnum {
WIN,
LOSE,
DRAW
}
public interface ElementVisitor {
ResultEnum visit(Rock rock);
ResultEnum visit(Paper paper);
ResultEnum visit(Scissors scissors);
}
public class PaperVisitor implements ElementVisitor {
@Override
public ResultEnum visit(Rock rock) {
return ResultEnum.WIN;
}
@Override
public ResultEnum visit(Paper paper) {
return ResultEnum.DRAW;
}
@Override
public ResultEnum visit(Scissors scissors) {
return ResultEnum.LOSE;
}
}
public class RockVisitor implements ElementVisitor {
@Override
public ResultEnum visit(Rock rock) {
return ResultEnum.DRAW;
}
@Override
public ResultEnum visit(Paper paper) {
return ResultEnum.LOSE;
}
@Override
public ResultEnum visit(Scissors scissors) {
return ResultEnum.WIN;
}
}
public class ScissorsVisitor implements ElementVisitor {
@Override
public ResultEnum visit(Rock rock) {
return ResultEnum.LOSE;
}
@Override
public ResultEnum visit(Paper paper) {
return ResultEnum.WIN;
}
@Override
public ResultEnum visit(Scissors scissors) {
return ResultEnum.DRAW;
}
}
public interface Element {
ResultEnum accept(ElementVisitor elementVisitor);
}
public class Paper implements Element {
@Override
public ResultEnum accept(ElementVisitor elementVisitor) {
return elementVisitor.visit(this);
}
}
public class Rock implements Element {
@Override
public ResultEnum accept(ElementVisitor elementVisitor) {
return elementVisitor.visit(this);
}
}
public class Scissors implements Element {
@Override
public ResultEnum accept(ElementVisitor elementVisitor) {
return elementVisitor.visit(this);
}
}
@SpringBootApplication
public class TestsApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(TestsApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
Element e1 = new Rock();
Element e2 = new Paper();
System.out.println(e1.accept(new PaperVisitor()));
System.out.println(e2.accept(new RockVisitor()));
}
}
Result:
WIN
LOSE
I think I understang the gist of it (avoid the instanceof operator) but it seems a bit cumbersome in the sense that if you have N visitable elements, you need to implement N*N methods. In this case it's only 9 and you can combine every element with itself and other elements, but I can't think of a real case scenario where this would happen (in a IO bound web app). Have you ever implemented this pattern in a real web app??
element.Accept(visitor)
aselement.Do(operation)
, and readvisitor.visit(ConcreteElement)
asoperation.ApplyTo(ConcreteElement)
. Client code doesn't know the concrete type of an element, it just chooses an operation, and passes it to the element abstraction; the operation (visitor) then figures out which concrete method to apply. 2/2