|
|||||||||||
| PREV NEXT | FRAMES NO FRAMES | ||||||||||
See:
Description
The dynamic dispatcher library, version 0.0.4.
This is preliminary documentation! It will be completed before the first 0.1 release.
This project was initially based on this paper (to be published in the ACM proceedings of the SEKE'04 conference).
Dynamic Dispatcher is a replacement for applying the VISITOR design
pattern.
It can be used to define new operations (called visitors) over unmodifiable
(domain) class hierarchies.
Summarized, the accept method of the VISITOR pattern is
replaced by an explicit dispatcher object.
Furthermore, the dispatcher object simulates covariant method overriding.
Thus a visitor class does not neccessarily define visit methods for
all domain classes.
Instead, the most appropriate visit method is chosen during dispatch.
E.g., dispatch(anArrow) calls visit(Line) if
visit(Arrow) is not defined in the visitor (see example below).
The library provides three concrete dispatcher factories to create a
dispatcher for a certain object. The default (ReflectionDispatcherFactory) uses reflection. It does not require
additional libraries.
When performance is an issue (e.g., when a large number of incocations must
be dispatched), the ByteCodeDispatcherFactory (requires bcel.jar) and the SourceCodeDispatcherFactory (require tools.jar) can be used.
The following example illustrates how this library can be used. It consists of
translate() would
be defined inside the Shape hierarchy it would not have been overridden in
Arrow), we do not provide a visit(Arrow a) method
It can be seen, that we do not have to modify Shape and co. in order to
realize translate.
If we had applied the standard VISITOR pattern, this is not possible. We
had to explicitly define visit(Arrow a) which then could call
visit((Line)a).
abstract class Shape {}
class Line extends Shape { float x1,y1,x2,y2; /* ... */ }
class Circle extends Shape { float x,y,r; /* ... */ }
class Picture extends Shape { ArrayList elements = new ArrayList(); /* ... */ }
class Arrow extends Line { /* ... */ }
class Translate {
float x,y;
// select the default dispatcher for "visit" methods
Dispatcher dsp = DispatcherFactory.createDefaultDispatcher(this);
public void dispatch(Shape s) { dsp.dispatch(s); }
public void visit(Line l) { l.x1+=x;l.y1+=y; l.x2+=x;l.y2+=y; }
public void visit(Circle c) { c.x+=x;c.y+=y; }
public void visit(Picture p) {
for (Iterator it=p.elements;it.hasNext();) {
Shape s = (Shape)it.next();
dsp.dispatch(s);
}
}
// no visit(Arrow), it is handled by visit(Line) !!
}
...
public static void main(String[] args) {
Picture p = new Picture();
Arrow a = new Arrow(1.0,1.0,2.0,4.0);
Circle c = new Circle(1.0,2.0,3.0);
p.add(a);p.add(c);
Translate t = new Translate(1.0,2.0);
t.dispatch(p);
}
|
|||||||||||
| PREV NEXT | FRAMES NO FRAMES | ||||||||||