Skip to content

Commit

Permalink
#590 add explanation for Visitor
Browse files Browse the repository at this point in the history
  • Loading branch information
iluwatar committed Jul 16, 2020
1 parent e98ad67 commit 68fa6f4
Showing 1 changed file with 182 additions and 3 deletions.
185 changes: 182 additions & 3 deletions visitor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,188 @@ tags:
---

## Intent
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.
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.

## Explanation

Real world example

> 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.
In plain words

> Visitor pattern defines operations that can be performed on the nodes of the data structure.
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**

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

```java
public abstract class Unit {

private 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 visitSoldier(Soldier soldier);

void visitSergeant(Sergeant sergeant);

void visitCommander(Commander commander);
}
```

Then we have the concrete units.

```java
public class Commander extends Unit {

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

@Override
public void accept(UnitVisitor visitor) {
visitor.visitCommander(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.visitSergeant(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.visitSoldier(this);
super.accept(visitor);
}

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

And then some concrete visitors.

```java
public class CommanderVisitor implements UnitVisitor {

private static final Logger LOGGER = LoggerFactory.getLogger(CommanderVisitor.class);

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

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

@Override
public void visitCommander(Commander commander) {
LOGGER.info("Good to see you {}", commander);
}
}

public class SergeantVisitor implements UnitVisitor {

private static final Logger LOGGER = LoggerFactory.getLogger(SergeantVisitor.class);

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

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

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

public class SoldierVisitor implements UnitVisitor {

private static final Logger LOGGER = LoggerFactory.getLogger(SoldierVisitor.class);

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

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

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

Finally we can show the power of visitors in action.

```java
commander.accept(new SoldierVisitor());
// Greetings soldier
// Greetings soldier
// Greetings soldier
// Greetings soldier
// Greetings soldier
// Greetings soldier
commander.accept(new SergeantVisitor());
// Hello sergeant
// Hello sergeant
commander.accept(new CommanderVisitor());
// Good to see you commander
```

## Class diagram
![alt text](./etc/visitor_1.png "Visitor")
Expand Down

0 comments on commit 68fa6f4

Please sign in to comment.