DOM2: abscence of Visitor in Iterators and Filters

I am curious if the Visitor design pattern has been considered for
inclusion in the DOM2 API?  IMO, it is a natural addition.  Initially, I
questioned the absence of a Visitor interface, then I questioned
myself.  I briefly, and incorrectly, concluded that Iterator was
sufficient.  Upon further reflection, though, I realized that Visitor is
complementary to Iterator.  From "Design Patterns" by the GoF [1]:

    "Who is responsible for traversing the object structure?...We
     can put responsibility for traversal in any of three places: the
     object structure [the DOM], the visitor, or in a separate
     iterator object..."

I considered whether the Filter interface could be used as a substitute
despite the semantic distaste of not actually using it for filtering. 
However, Filter lacks the double-dispatch technique, and "this is the
key to the Visitor pattern" [1].  Through double-dispatch and either
polymorphism or appropriate method names, the visitor has a visit method
invoked for the appropriate Node subclass.  Achieving similar results
with Filter would require a switch statement or similar conditional on
the node type, which is decidedly non-Object-Oriented, followed by
casting to a subclass, which is potentially dangerous.

Based on these conclusions, I decided that a Visitor interface would be
a useful extension to Iterators and Filters.  I've included a basic
example [3] of what a DOM Visitor interface might look like.  I'm sure
the WG is aware of IBM's Visitor interface in their TX API as another
example.


[1] "Design Patterns, Elements of Reusable Object-Oriented Software";
    by Erich Gamma, et. al.; Chapter 5, Visitor, Implementation

[2] IBM xml4j <uri:http://www.alphaworks.ibm.com/> (sorry, Alphaworks
seems
    to be down at the moment, so I don't have the full URI)

[3] Visitor, Java binding example

/** interface for visiting nodes of a DOM document */
public interface Visitor {
        /*
        multiple visit methods with signatures that only differ
        by the argument and rely on method overloading (polymorphism?)
        would be preferable.  However, including the type in the
        method names appears to be more prevalent in the examples I've
        seen
        */
        public void visitAttr(Attr attr);

        public void visitCDATASection(CDATASection cdataSection);

        public void visitComment(Comment comment);

        public void visitDocument(Document document);

        public void visitDocumentFragment(DocumentFragment
documentFragment);

        public void visitDocumentType(DocumentType documentType);

        public void visitElement(Element element);

        public void visitEntity(Entity entity);

        public void visitEntityReference(EntityReference
entityReference);

        public void visitNotation(Notation notation);

        public void visitProcessingInstruction(
                        ProcessingInstruction processingInstruction);

        public void visitText(Text text);
}

/*
every concrete sub-type of Node must implement an accept method, and
call the appropriate visit method for the sub-type.  Here's an example
for a concrete Element class and a concrete Text class
*/

public class ConcreteElement implements org.w3c.dom.Element {
	/* other element methods */
	...

	/* accept a visitor */
	void accept(Visitor visitor) {
		visitor.visitElement(this);
	}
}

public class ConcreteText implements org.w3c.dom.Text {
	/* other Text methods */
	...

	/* accept a visitor */
	void accept(Visitor visitor) {
		visitor.visitText(this);
	}
}


-- 
Tim Taylor                sigma6 Interactive Media
ttaylor@sigma6.com        conceive : construct : connect tm

Received on Wednesday, 4 August 1999 17:23:35 UTC