Files
java-design-patterns/visitor
Ilkka Seppälä 6cd2d0353a docs: Content SEO updates (#2990)
* update yaml frontmatter format

* update abstract document

* update abstract factory

* use the new pattern template

* acyclic visitor seo

* adapter seo

* ambassador seo

* acl seo

* aaa seo

* async method invocation seo

* balking seo

* bridge seo

* builder seo

* business delegate and bytecode seo

* caching seo

* callback seo

* chain seo

* update headings

* circuit breaker seo

* client session + collecting parameter seo

* collection pipeline seo

* combinator SEO

* command seo

* cqrs seo

* commander seo

* component seo

* composite seo

* composite entity seo

* composite view seo

* context object seo

* converter seo

* crtp seo

* currying seo

* dao seo

* data bus seo

* data locality seo

* data mapper seo

* dto seo

* decorator seo

* delegation seo

* di seo

* dirty flag seo

* domain model seo

* double buffer seo

* double checked locking seo

* double dispatch seo

* dynamic proxy seo

* event aggregator seo

* event-based asynchronous seo

* eda seo

* event queue seo

* event sourcing seo

* execute around seo

* extension objects seo

* facade seo

* factory seo

* factory kit seo

* factory method seo

* fanout/fanin seo

* feature toggle seo

* filterer seo

* fluent interface seo

* flux seo

* flyweight seo

* front controller seo

* function composition seo

* game loop seo

* gateway seo

* guarded suspension seo

* half-sync/half-async seo

* health check seo

* hexagonal seo

* identity map seo

* intercepting filter seo

* interpreter seo

* iterator seo

* layers seo

* lazy loading seo

* leader election seo

* leader/followers seo

* lockable object seo

* rename and add seo for marker interface

* master-worker seo

* mediator seo

* memento seo

* metadata mapping seo

* microservice aggregator seo

* api gw seo

* microservices log aggregration seo

* mvc seo

* mvi seo

* mvp seo

* mvvm seo

* monad seo

* monitor seo

* monostate seo

* multiton seo

* mute idiom seo

* naked objects & notification seo

* null object seo

* object mother seo

* object pool seo

* observer seo

* optimistic locking seo

* page controller seo

* page object seo

* parameter object seo

* partial response seo

* pipeline seo

* poison pill seo

* presentation model seo

* private class data seo

* producer-consumer seo

* promise seo

* property seo

* prototype seo

* proxy seo

* queue-based load leveling seo

* reactor seo

* registry seo

* repository seo

* RAII seo

* retry seo

* role object seo

* saga seo

* separated interface seo

* serialized entity seo

* serialized lob seo

* servant seo

* server session seo

* service layer seo

* service locator seo

* service to worker seo

* sharding seo

* single table inheritance seo

* singleton seo

* spatial partition seo

* special case seo

* specification seo

* state seo

* step builder seo

* strangler seo

* strategy seo

* subclass sandbox seo

* table module seo

* template method seo

* throttling seo

* tolerant reader seo

* trampoline seo

* transaction script seo

* twin seo

* type object seo

* unit of work seo

* update method seo

* value object seo

* version number seo

* virtual proxy seo

* visitor seo

* seo enhancements

* seo improvements

* SEO enhancements

* SEO improvements

* SEO additions

* SEO improvements

* more SEO improvements

* rename hexagonal + SEO improvements

* SEO improvements

* more SEO stuff

* SEO improvements

* SEO optimizations

* SEO enhancements

* enchance SEO

* improve SEO

* SEO improvements

* update headers
2024-06-08 19:54:44 +03:00
..
2019-12-07 18:03:49 +02:00
2024-05-27 14:59:50 +03:00
2022-09-14 23:22:24 +05:30
2024-06-08 19:54:44 +03:00

title, shortTitle, description, category, language, tag
title shortTitle description category language tag
Visitor Pattern in Java: Implementing Robust Operations Across Diverse Object Structures Visitor Explore the Visitor design pattern in Java with detailed examples and class diagrams. Learn how to implement operations without altering object structures for clean and maintainable code. Behavioral en
Decoupling
Extensibility
Gang of Four
Object composition
Polymorphism

Intent of Visitor Design Pattern

To represent 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.

Detailed Explanation of Visitor Pattern with Real-World Examples

Real-world example

An analogous real-world example of the Visitor design pattern can be seen in a museum tour guide system. Imagine a museum where visitors can take guided tours to learn about different types of exhibits, such as paintings, sculptures, and historical artifacts. Each exhibit type requires a different explanation, which is provided by specialized tour guides.

In this scenario, the exhibits are like the elements in the Visitor pattern, and the tour guides are like the visitors. The museum structure remains unchanged, but new guides with new types of tours (operations) can be added without modifying the exhibits themselves. Each guide (visitor) implements a specific way to interact with the exhibits, providing detailed explanations according to their specialization, thereby separating the operations from the objects they operate on.

In plain words

The Java Visitor pattern defines operations that can be performed on nodes of various data structures, enhancing Java application extensibility.

Wikipedia says

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 the structures.

Programmatic Example of Visitor Pattern in Java

Consider a tree structure with army units. Commander has two sergeants under it and each sergeant has three soldiers under them. Given that the hierarchy implements the visitor pattern, we can easily create new objects that interact with the commander, sergeants, soldiers, or all of them.

Given the army unit example from above, we first have the Unit and UnitVisitor base types.

public abstract class Unit {

  private final Unit[] children;

  public Unit(Unit... children) {
    this.children = children;
  }

  public void accept(UnitVisitor visitor) {
    Arrays.stream(children).forEach(child -> child.accept(visitor));
  }
}

public interface UnitVisitor {

  void visit(Soldier soldier);

  void visit(Sergeant sergeant);

  void visit(Commander commander);
}

Then we have the concrete units Commander, Sergeant, and Soldier.

public class Commander extends Unit {

  public Commander(Unit... children) {
    super(children);
  }

  @Override
  public void accept(UnitVisitor visitor) {
    visitor.visit(this);
    super.accept(visitor);
  }

  @Override
  public String toString() {
    return "commander";
  }
}
public class Sergeant extends Unit {

  public Sergeant(Unit... children) {
    super(children);
  }

  @Override
  public void accept(UnitVisitor visitor) {
    visitor.visit(this);
    super.accept(visitor);
  }

  @Override
  public String toString() {
    return "sergeant";
  }
}
public class Soldier extends Unit {

  public Soldier(Unit... children) {
    super(children);
  }

  @Override
  public void accept(UnitVisitor visitor) {
    visitor.visit(this);
    super.accept(visitor);
  }

  @Override
  public String toString() {
    return "soldier";
  }
}

Here are the concrete visitors CommanderVisitor, SergeantVisitor, and SoldierVisitor.

@Slf4j
public class CommanderVisitor implements UnitVisitor {

  @Override
  public void visit(Soldier soldier) {
    // Do nothing
  }

  @Override
  public void visit(Sergeant sergeant) {
    // Do nothing
  }

  @Override
  public void visit(Commander commander) {
    LOGGER.info("Good to see you {}", commander);
  }
}
@Slf4j
public class SergeantVisitor implements UnitVisitor {

  @Override
  public void visit(Soldier soldier) {
    // Do nothing
  }

  @Override
  public void visit(Sergeant sergeant) {
    LOGGER.info("Hello {}", sergeant);
  }

  @Override
  public void visit(Commander commander) {
    // Do nothing
  }
}
@Slf4j
public class SoldierVisitor implements UnitVisitor {

  @Override
  public void visit(Soldier soldier) {
    LOGGER.info("Greetings {}", soldier);
  }

  @Override
  public void visit(Sergeant sergeant) {
    // Do nothing
  }

  @Override
  public void visit(Commander commander) {
    // Do nothing
  }
}

Finally, we can show the power of visitors in action.

public static void main(String[] args) {

    var commander = new Commander(
            new Sergeant(new Soldier(), new Soldier(), new Soldier()),
            new Sergeant(new Soldier(), new Soldier(), new Soldier())
    );
    commander.accept(new SoldierVisitor());
    commander.accept(new SergeantVisitor());
    commander.accept(new CommanderVisitor());
}

Program output:

14:58:06.115 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier
14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier
14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier
14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier
14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier
14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier
14:58:06.118 [main] INFO com.iluwatar.visitor.SergeantVisitor -- Hello sergeant
14:58:06.118 [main] INFO com.iluwatar.visitor.SergeantVisitor -- Hello sergeant
14:58:06.118 [main] INFO com.iluwatar.visitor.CommanderVisitor -- Good to see you commander

Detailed Explanation of Visitor Pattern with Real-World Examples

Visitor

When to Use the Visitor Pattern in Java

Use the Visitor pattern when

  • Implement the Visitor design pattern in Java when you need to efficiently perform operations across groups of similar objects without modifying their classes, and you want to avoid polluting their classes with this operation.
  • Use it when a class structure is stable, but you need to perform new operations on the structure without changing it.
  • It's beneficial when the set of classes are fixed and only the operations need to be extended.

Visitor Pattern Java Tutorials

Real-World Applications of Visitor Pattern in Java

Benefits and Trade-offs of Visitor Pattern

Benefits:

  • Simplifies adding new operations: Adding a new operation is straightforward because you can add a new visitor without changing existing code.
  • Single Responsibility Principle: The Visitor pattern allows you to move related behavior into one class.
  • Open/Closed Principle: Elements can stay closed to modification while visitors are open to extension.

Trade-offs:

  • Adding new element classes: If you need to add new types of elements, you'll need to change both the visitor interface and all of its concrete visitors.
  • Circular dependencies: In complex systems, this pattern can introduce circular dependencies between visitor and element classes.
  • Breaking encapsulation: Visitor pattern requires that the element classes expose enough details to allow the visitor to do its job, potentially breaking encapsulation.
  • Composite: The Visitor pattern is often used in conjunction with the Composite pattern, where the visitor can perform operations over a composite structure.
  • Interpreter: Visitors can be used to implement the non-terminal expressions in the Interpreter pattern.
  • Strategy: Visitor can be considered a way of making strategies work on objects that they were not designed to operate on.

References and Credits