When using the Visitor Pattern, can the visit(object)
method update or modify the object it visits or is it simply supposed to only use the object in performing some computation and returning the computation result?
Thanks
When using the Visitor Pattern, can the visit(object)
method update or modify the object it visits or is it simply supposed to only use the object in performing some computation and returning the computation result?
Thanks
All examples of the visitor pattern I've seen don't change the objects visited.
But as far as I understand the definition given on Wikipedia, it's just not defined what the visitor can do with the visited objects.
Even the definition from Gang of Four (also in the wiki article) doesn't touch that subject:
Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
Therefore I'd say that a visitor may call any accessible method on an object it visits as this is not part of the visitor pattern - the visitor pattern just describes how this objects are made accessible.
In the following example the mailer is the "element" and the "visitor" is the lambda expression which is passed to send()
.
As you can see here (and in many other examples) the visitor can modify the element's internal state. That said, changing the element's internal state is not a requirement: it could be that the visitor will call some of the element's methods in order to do all sorts of actions: pass a message to another object, run a computation and print to screen the result and etc.
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
Mailer.send(mailer ->
mailer.from("[email protected]")
.to("[email protected]")
.body("what's up bud?")
);
}
}
class Mailer {
String fromStr;
String toStr;
String bodyStr;
public Mailer from(String from) {
this.fromStr = from;
return this;
}
public Mailer to(String to) {
this.toStr = to;
return this;
}
public Mailer body(String body) {
this.bodyStr = body;
return this;
}
public static void send(Consumer<Mailer> loader) {
Mailer mailer = new Mailer();
loader.accept(mailer);
System.out.println(mailer);
// ... send the email
}
@Override
public String toString() {
return "From: " + fromStr + "\n" +
"To: " + toStr + "\n" +
"Body: " + bodyStr;
}
}
The visitor pattern is not meant to modify the object's state. Instead, its purpose is to implement specific functionality.
A paradigm would be adding the functionality of counting the elements of a tree, an example I explain in this Case Study: Applied Design Patterns and Software Architecture.
The CharacterVisitor
which holds the count value of the total visited CustomCharacter
class has the following structure:
/**
* Implements the Visitor pattern
*/
class CharacterVisitor
{
private int count = 0;
void visitCharacter(CustomCharacter customCharacter)
{
count++;
}
public int getResult()
{
return count;
}
}
The countCharacters()
function, which implements the logic of the Visitor pattern:
/**
* Counts the words in the text by using the Iterator and Visitor patterns.
*/
int countCharacters()
{
CharacterVisitor characterVisitor = new CharacterVisitor();
CharacterIterator characterIterator =
new CharacterIterator(editorController.getCompositeBuilder());
characterIterator.first();
while(!characterIterator.isDone())
{
CustomCharacter customCharacter = characterIterator.getCurrent();
customCharacter.accept(characterVisitor);
characterIterator.next();
}
return characterVisitor.getResult();
}
Note that in this example I also implement the Iterator pattern as well. I go in to more details in the case study.
You can find the complete code in this github repository, where I explain all of the design patterns mentioned in the legendary GOF book.
The visit(object) method is able to update or modify the object it visits. That said it is only able to update or modify fields or properties that are both public and not readonly on that class. Alternatively the visit method could use public methods that object exposes to update or modify the object.
© 2022 - 2024 — McMap. All rights reserved.