April 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Working With Design Patterns: Visitor, Page 2

  • January 28, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

Listing 4: HierarchyField.

package util;

import java.lang.reflect.*;

public class HierarchyField {
   private Field field;

   public HierarchyField(Field field) {
      this.field = field;
      field.setAccessible(true);
   }

   public String name() {
      return field.getName();
   }

   public Object getValue(Object object) {
      try {
         return field.get(object);
      } catch (IllegalAccessException e) {
         throw new RuntimeException();
      }
   }

   @Override
   public boolean equals(Object object) {
      if (object == null || !(object instanceof HierarchyField))
         return false;
      HierarchyField that = (HierarchyField)object;
      return that.field.getName().equals(this.field.getName());
   }

   public Class<?> type() {
      return field.getType();
   }
}

It's up to the visitor implementation to decide what to do with each of these callbacks. Listing 5 shows an implementation for the XML transformer. The XmlBuilder class implements the Visitor interface, providing appropriate logic for each of the visit, depart, and visitPrimitiveAttribute methods.

Listing 5: Implenting the XML transformer.

import util.*;
import visitor.*;

public class XmlBuilder implements Visitor {
   private static final String EOL =
      System.getProperty("line.separator");
   private static final String PAD = "  ";

   private int level = 0;
   private StringBuilder builder;

   public XmlBuilder(StringBuilder builder) {
      this.builder = builder;
   }

   @Override
   public void visit(HierarchyObject instance) {
      indent(++level);
      appendLine(beginTag(instance.typeName()));
   }

   @Override
   public void depart(HierarchyObject instance) {
      indent(level);
      appendLine(endTag(instance.typeName()));
      --level;
   }

   @Override
   public void visitPrimitiveAttribute(HierarchyObject instance,
                                       HierarchyField attribute) {
      indent(level + 1);
      appendLine(beginTag(attribute.name())
            + instance.valueString(attribute)
            + endTag(attribute.name()));
   }

   private void indent(int levels) {
      for (int i = 0; i < levels; i++)
         append(PAD);
   }

   private String beginTag(String text) {
      return "<" + text + ">";
   }

   private String endTag(String text) {
      return "</" + text + ">";
   }

   private void appendLine(String text) {
      builder.append(text + EOL);
   }

   private void append(String text) {
      builder.append(text);
   }
}

The main points? XmlBuilder isn't fettered with the navigation and reflection logic, making it very easy to comprehend. And, HierarchyWalker supports the ability to do something other than produce an XML document.

Visitor does present challenges, particularly as things change. Several variants of the visitor pattern exist to try and circumvent these issues. But as complex as visitor can be, the heart of the pattern is about simplifying things through use of the SRP.

Figure 1: Visitor

About the Author

Jeff Langr is a veteran software developer with over a quarter century of professional software development experience. He's written two books, including Agile Java: Crafting Code With Test-Driven Development (Prentice Hall) in 2005. Jeff is contributing a chapter to Uncle Bob Martin's upcoming book, Clean Code. Jeff has written over 50 published articles on software development, with more than a couple dozen appearing at Developer.com You can find out more about Jeff at his site, http://langrsoft.com, or you can contact him via email at jeff at langrsoft dot com.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel