This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes OO, Patterns, UML and Refactoring and the fly likes Visitor - decorator problem Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Visitor - decorator problem" Watch "Visitor - decorator problem" New topic
Author

Visitor - decorator problem

Alik Elzin
Greenhorn

Joined: Sep 19, 2002
Posts: 15
Hi all.
I just realized that passing this (myself) to methods
is very dangerous because classes that do that can never be decorated.
Why ?
Consider a case where a class "AImpl" is decorated by class "ADecImpl" (both implementing "A").
"AImpl" passes itself to some method "Temp.temp(A a)".

When "AImpl" passes itself,
the decorated class gets lost and
from now on never used in Temp.temp(
a a).


Specifically, the visitor design pattern is based on passing itself
(in recursion like structures of trees) and
the elements it visits are passing themselves to the visitor.

Thus, whenever I have a visitor, or more generally, a class that passes itself on,
I cannot use decoration on it - not on the visitors and not on the visited.

I c the decorator design pattern as a sort of dynamic inheritance and
suggest that each object in the world be "Decoratable", having 2 methods:
setThis() and getThis().

The problem of this solution is when having TWO decorators to ONE object - which one of them is this ?

What do you think ?
Is there a proper solution to the problem ?

I like the decorator very much because
it helps us design applications using interfaces and not implementations, because
it encapsulates data and for a whole other reasons.

Hope to find solution to the problem....

Regards,
Alik.

[ January 11, 2007: Message edited by: Alik Elzin ]

[ January 11, 2007: Message edited by: Alik Elzin ]
[ January 11, 2007: Message edited by: Alik Elzin ]
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
It seems to me that the Visitor pattern would still work if the Decorator implemented the accept method by passing the Decorator to the Visitor instead of the decorated object.

Am I missing something?


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Alik Elzin
Greenhorn

Joined: Sep 19, 2002
Posts: 15
Hi
You are correct - The "accept" would just need to be written twice -
In the decorated class and in the decorating one (We cannot always inherit this code...).

The bigger problem is that the visitor cannot be decorated.

The general problem is that when a class passes itself (this),
the class cannot be decorated, because the decoration will vanish.

What I'm trying to ask is whether
we should avoid passing "this" ?

If we should avoid passing ourselves on,
people should know that - it is a good practice.
If not, how can we overcome the problem stated here ?

Regards,
Alik.

[ January 11, 2007: Message edited by: Alik Elzin ]
[ January 11, 2007: Message edited by: Alik Elzin ]
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Alik Elzin:
The bigger problem is that the visitor cannot be decorated.


I don't see it. Can you post a small example that shows the problem you are thinking of?


The general problem is that when a class passes itself (this),
the class cannot be decorated, because the decoration will vanish.


I'd rather say that the method that gets passed the this reference simply will not see the decoration. Whether that's actually a problem will depend on the specific circumstances, of course.


What I'm trying to ask is whether
we should avoid passing "this" ?

If we should avoid passing ourselves on,
people should know that - it is a good practice.
If not, how can we overcome the problem stated here ?


It's certainly a problem that is good to be aware of, but also one that doesn't manifest very often, in my experience. I think that avoiding passing "this" as a hard and fast rule would be throwing out the baby with the bathwater.
Alik Elzin
Greenhorn

Joined: Sep 19, 2002
Posts: 15
Look at the following code:

//specific logging visitor
public class ElementVisitorLogger extends VisitorDecorator implements Visitor{

public ElementVisitorLogger(Visitor decorated) {
super(decorated);
}

void visit(ElementSpecificA a) {
write("Visiting element " + a);
getDecorated().visit(a);
write("Finished visiting element " + a);
}

}

public interface Visitor {
void visit(ElementSpecificA a);
//visits to other specific elements...
}

public interface Element {
void accept(Visitor visitor);
}

//specific element
public class ElementSpecificA implements Element {
List<Element> getChildren();
}

//specific visitor
public class TraversingVisitor implements Visitor {
void visit(ElementSpecificA a) {
//do "a"'s logic...

for(Element child : a.getChildren()) {
a.accept(this);
}
}
}

What is written above is logic for logging visitor actions.

We try doing so by decorating a visitor (specifically "TraversingVisitor" but we should not know this - just some Visitor).

But, when the visitor will pass itself further on to child elements, the decoration will vanish.

This is just an example.
I'm sure you saw objects in your past that pass themselves ("this") to methods as a parameter.
The interfaces of such classes cannot be decorated or the decoration will vanish during the program flow.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
But, when the visitor will pass itself further on to child elements, the decoration will vanish.


I've never made the visitor pass itself (this) anywhere. Maybe that's a variation on Visitor Pattern I just haven't bumped into. I've always seen the object graph responsible for passing the visitor around. Part of the beauty is that the visitor doesn't have to know how to navigate the graph.

So some other object creates the visitor (and decorates it if need be) and passes it into the graph. But the nodes pass "this" to the visitor. Maybe that's what you meant? We could get around that I'm sure.

I'll join in saying the original point about this stripping off decorators is pretty neat. Guess I haven't used decorator enough to run into it. Something interesting to watch out for in the future.


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Alik Elzin
Greenhorn

Joined: Sep 19, 2002
Posts: 15
Hey.

I think it's better in a tree structure for the visitor to traverse itself in the tree rather than the nodes passing their children to the decorator in addition to themselves.
The above is true because you don't always want to visit the children of a node, but rather just the node itself.
If the node passes its children as well, such a case cannot be implemented.

Creating a traversing visitor is very easy to implement because it already knows the structure of the elements it visits.

Than, if you want to reuse the traversing algorithm, just inherit it by your own logic visitor.

Using a traversing visitor (DFS, BFS) encapsulates the iteration logic from the nodes of the tree.

Regards,
Alik.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Ah, I see how decorating a traversing visitor could be a problem, yes. I don't use those very often, and I never felt the need to decorate one, as far as I remember.

So the Decorator pattern doesn't mix well with a traversing Visitor. Good to know, but not something to worry too much about, I'd say...
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
My favorite visitor implementation is a closed, stable object graph that does the navigation itself. I just call accept() on the top node and it does the rest. This is very nice because the navigation is nasty enough that I was thrilled to never work it out.

I went back to GoF to see where they put the traversal responsibility and it's actually outside the object graph and the visitor in an "object structure" with iterator functionality. That's ok with me, too. As a user of the object graph I still don't have to know or ever repeat the navigation.
 
wood burning stoves
 
subject: Visitor - decorator problem
 
Similar Threads
What is dependency injection?
Why pool stateless session beans when you can get by with one instance?
Thread Scheduling - reg.
inner class
protected specifier for Object class