Visitor pattern is a better design when we have extendable visitor list but operate on pretty stable element list, we can easily extend the visitor and give specific implementation methods without touching exisitng code.
There are several roles in visitor pattern, visitor (operator), elements (visotor operates on), object structure which will maintian the visitor list.
Take an example, we have a tour company, have a stable resort list: Great Wall, Taj Mahal and Grand palace, but the tourist group can always change and they may raise special request during the tour, we can apply visitor pattern to solve it.
Concrete visitor class will provide visit method implement details,
/**
* @Author Carter Deng
* @Date 2021/11/13
* Concrete visitor class
*/
public class Carter extends Visitor {
private String visitorName = "Carter";
@Override
public void visitGreatWall(GreatWall greatWall) {
System.out.println(visitorName + " comes to visit Great Wall");
}
@Override
public void visitTajMahal(TajMahal tajMahal) {
System.out.println(visitorName + " comes to visit Taj Mahal");
}
}
for each concrete resort class, it will provide accept method, which will call back of visitor class visit method, just allow visitor is able to visit the concrete emelement.
/**
* @Author Carter Deng
* @Date 2021/11/13
* Concrete element class
*/
public class TajMahal extends Resort{
@Override
public void accept(Visitor visitor) {
visitor.visitTajMahal(this);
}
}
Object structure class will maintain concrete visitor list.
/**
* @Author Carter Deng
* @Date 2021/11/13
*/
public class ObjectStrcture {
private List<Visitor> visitors;
public ObjectStrcture() {
this.visitors = new ArrayList<>();
}
public List<Visitor> addVisitor(Visitor v){
this.visitors.add(v);
return this.visitors;
}
public void displayVisitList(){
this.visitors.forEach(visitor->visitor.visitGreatWall(new GreatWall()));
this.visitors.forEach(visitor->visitor.visitTajMahal(new TajMahal()));
}
}