• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Visitor - decorator problem

 
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Alik Elzin
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 15
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Alik Elzin
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
reply
    Bookmark Topic Watch Topic
  • New Topic