|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
This interface implements part of the visitor pattern for nodes.
In object-oriented design a pattern has been established to let one class
react on the type of some object. Consider a tree composed of different
types of nodes all implementing a same base interface and some of them
having extensions of the interface. This is the situation for
Node
s for which several types
exist.
The original idea was to attach the desired functionality to the nodes and
let it have one common method to invoke it. This turns out not to be
practical for modular components where the algorithm might be exchanged.
This is the case for the
DocumentWriter
which might produce Text, PDF, DVI, or some other output format. Any new
implementation of this interface would have the need to extend the Node
classes.
The other simplistic solution is to use a large switch, or cascaded if-then-else, to differentiate the cases. This kind of code is cumbersome to maintain. Whenever a new type of node is added you have to remember all places which need adaption.
This problem is solved in the visitor pattern. Each class or interface of the nodes has to provide one method called visit() here. This method has as one argument the visitor which should be called back. The visitor is defined by this interface. He has to provide a set of methods which allow him to differentiate the types of the nodes.
Each node has to implement the method visit() in a way that the appropriate method from the visitor interface is invoked. Thus as a result the nodes and the algorithm are decoupled.
The actions during the use of a NodeVisitor is illustrated in the following sequence diagram.
In this diagram a NodeVisitor is assumed to process two nodes. The first one
is a CharNode
and the
second one is a GlueNode
.
We assume that the concrete sub-type of
Node
to be processed is not
known. For instance it can be passed to the initial method in a
NodeList
.
The first Node is processed by invoking the method visit(). The first argument is the reference to the current instanceof the NodeVisitor. Since the method is defined in CharNode to delegate it to the NodeVisitor by invoking the method visitChar(). Now the real work can be performed in the calling instance. Here the sub-type is known and can be taken into account.
After the return to the caller the second node can be taken into account. The procedure is the same: visit() is invoked. But now the delegation used the method visitGlue(). Thus in the calling instance the GlueNode can be processed specially.
Consider you have a class implementing DocumentWriter with a method which needs to react differently on different node types. The first approximation looks as follows:
public class MyDocumentWriter implements DocumentWriter { public void myMethod(final Node node) { // Do something with node depending on its type } }
Now we can add the NodeVisitor interface. Thus we are forced to define a bunch of methods declared in this interface:
public class MyDocumentWriter implements DocumentWriter, NodeVisitor { public void myMethod(final Node node) { // Do something with node depending on its type } public Object visitAdjust(final AdjustNode node, final Object arg) { // do something for adjust nodes } public Object visitChar(final CharNode node, final Object arg) { // do something for char nodes } // and many others.. }
Now we just have to make sure that those methods are invoked. This is done with the method visit() of the Node. The signature allows us to provide two additional arguments and receive a return value. Since we want to do something with the node itself, this node is provided with the correct type to the node visitor. The second argument can be casted to the appropriate type.
In the visit methods we can now savely assume that the node is of the named type and cast the object to have access to its public methods.
public class MyDocumentWriter implements DocumentWriter, NodeVisitor { public void myMethod(final Node node) { node.visit(this, "some value"); } public Object visitAdjust(final AdjustNode node, final Object arg) { String s = (String) arg; // do something for adjust nodes } public Object visitChar(final CharNode node, final Object arg) { String s = (String) arg; // do something for char nodes } // and many others.. }
In the example above we have not used the additional argument or the return value. In the visit methods we are free to use them in all ways we like.
The definition of the parameters and the return value are rather general. Thus it is possible to use the visitor pattern in several different situations.
The visitor is not necessarily the class MyDocumentWriter. If this class contains several methods which need to distinguish the types of the nodes it is possible to use another class as visitor, e.g. an inner class.
Method Summary | |
java.lang.Object |
visitAdjust(AdjustNode node,
java.lang.Object value)
This method is called when an AdjustNode
has been encountered. |
java.lang.Object |
visitAfterMath(AfterMathNode node,
java.lang.Object value)
This method is called when an AfterMathNode
has been encountered. |
java.lang.Object |
visitAlignedLeaders(AlignedLeadersNode node,
java.lang.Object value)
This method is called when an AlignedLeadersNode
has been encountered. |
java.lang.Object |
visitBeforeMath(BeforeMathNode node,
java.lang.Object value)
This method is called when a BeforeMathNode
has been encountered. |
java.lang.Object |
visitCenteredLeaders(CenteredLeadersNode node,
java.lang.Object value)
This method is called when a CenteredLeadersNode
has been encountered. |
java.lang.Object |
visitChar(CharNode node,
java.lang.Object value)
This method is called when a CharNode
has been encountered. |
java.lang.Object |
visitDiscretionary(DiscretionaryNode node,
java.lang.Object value)
This method is called when a DiscretionaryNode
has been encountered. |
java.lang.Object |
visitExpandedLeaders(ExpandedLeadersNode node,
java.lang.Object value)
This method is called when an ExpandedLeadersNode
has been encountered. |
java.lang.Object |
visitGlue(GlueNode node,
java.lang.Object value)
This method is called when a GlueNode
has been encountered. |
java.lang.Object |
visitHorizontalList(HorizontalListNode node,
java.lang.Object value)
This method is called when a HorizontalListNode
has been encountered. |
java.lang.Object |
visitInsertion(InsertionNode node,
java.lang.Object value)
This method is called when an InsertionNode
has been encountered. |
java.lang.Object |
visitKern(KernNode node,
java.lang.Object value)
This method is called when a KernNode
has been encountered. |
java.lang.Object |
visitLigature(LigatureNode node,
java.lang.Object value)
This method is called when a LigatureNode
has been encountered. |
java.lang.Object |
visitMark(MarkNode node,
java.lang.Object value)
This method is called when a MarkNode
has been encountered. |
java.lang.Object |
visitPenalty(PenaltyNode node,
java.lang.Object value)
This method is called when a PenaltyNode
has been encountered. |
java.lang.Object |
visitRule(RuleNode node,
java.lang.Object value)
This method is called when a RuleNode
has been encountered. |
java.lang.Object |
visitSpace(SpaceNode node,
java.lang.Object value)
This method is called when a SpaceNode
has been encountered. |
java.lang.Object |
visitVerticalList(VerticalListNode node,
java.lang.Object value)
This method is called when a VerticalListNode
has been encountered. |
java.lang.Object |
visitVirtualChar(VirtualCharNode node,
java.lang.Object value)
This method is called when a VirtualCharNode
has been encountered. |
java.lang.Object |
visitWhatsIt(WhatsItNode node,
java.lang.Object value)
This method is called when a WhatsItNode
has been encountered. |
Method Detail |
public java.lang.Object visitAdjust(AdjustNode node, java.lang.Object value) throws GeneralException
AdjustNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitAfterMath(AfterMathNode node, java.lang.Object value) throws GeneralException
AfterMathNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitAlignedLeaders(AlignedLeadersNode node, java.lang.Object value) throws GeneralException
AlignedLeadersNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitBeforeMath(BeforeMathNode node, java.lang.Object value) throws GeneralException
BeforeMathNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitCenteredLeaders(CenteredLeadersNode node, java.lang.Object value) throws GeneralException
CenteredLeadersNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitChar(CharNode node, java.lang.Object value) throws GeneralException
CharNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitDiscretionary(DiscretionaryNode node, java.lang.Object value) throws GeneralException
DiscretionaryNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitExpandedLeaders(ExpandedLeadersNode node, java.lang.Object value) throws GeneralException
ExpandedLeadersNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitGlue(GlueNode node, java.lang.Object value) throws GeneralException
GlueNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitHorizontalList(HorizontalListNode node, java.lang.Object value) throws GeneralException
HorizontalListNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitInsertion(InsertionNode node, java.lang.Object value) throws GeneralException
InsertionNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitKern(KernNode node, java.lang.Object value) throws GeneralException
KernNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitLigature(LigatureNode node, java.lang.Object value) throws GeneralException
LigatureNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitMark(MarkNode node, java.lang.Object value) throws GeneralException
MarkNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitPenalty(PenaltyNode node, java.lang.Object value) throws GeneralException
PenaltyNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitRule(RuleNode node, java.lang.Object value) throws GeneralException
RuleNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitSpace(SpaceNode node, java.lang.Object value) throws GeneralException
SpaceNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitVerticalList(VerticalListNode node, java.lang.Object value) throws GeneralException
VerticalListNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitVirtualChar(VirtualCharNode node, java.lang.Object value) throws GeneralException
VirtualCharNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an errorpublic java.lang.Object visitWhatsIt(WhatsItNode node, java.lang.Object value) throws GeneralException
WhatsItNode
has been encountered.
node
- the first parameter for the visitor is the node visitedvalue
- the second parameter for the visitor
GeneralException
- in case of an error
|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |