Alignment: Chaotic Java

Wednesday, December 14, 2005

Factory Design Pattern made simple using Enums

Writing X2J I encountered a state most of us encountered before: The need for a Factory Design Pattern. In my situation, during parsing (using SAX), there is an interface called ContentHandler (javadoc) which is required by my handler. The handler should be created according to the type of the element being currently parsed. An obvious case for a Factory.

Now, I already have an enum such as:


public enum ObjectType {
    ELEMENT,
    ARRAY;
}


I can have a factory class like this:


public class HandlerFactory() {
    /* .. singleton stuff .. */

    public ContentHandler createHandler(ObjectType type) throws X2JException {
        ContentHandler handler = handlers.get(type);

        if (handler == null) {
          switch (type) {
            case ELEMENT:
              handler = new ElementHandler();
              break;
            case ARRAY:
              handler = new ArrayHandler();
              break;
          }
          handlers.put(type, handler);
        }

        return handler;
    }
}


However, since enums can now have properties and methods as part of Tiger's new features and they're not just a group of constant integers, I can do the following:


public enum ObjectType {
    ELEMENT(ElementHandler.class),
    ARRAY(ArrayHandler.class);

    public Class<? extends ContentHandler> handlerType;

    ObjectType(Class<? extends ContentHandler> handlerType) {
        this.handlerType = handlerType;
    }
}


And the factory becomes very simple, such as:


public ContentHandler createHandler(ObjectType type) throws X2JException {
        ContentHandler handler = handlers.get(type);

        if (handler == null) {
            try {
                handler = type.handlerType.newInstance();
            } catch (Exception e) {
                throw new X2JException(String.format(\"Fail to create handler %s\", type), e);
            }

            handlers.put(type, handler);
        }

        return handler;
    }


The added bonus is that I don't have to worry about this factory class anymore - Whatever new enum values I add, the factory will not be changed. I wish I could somehow get away from calling newInstance(), but I guess it's neglegible because I do that once per enum value, which isn't a lot.

Simple, eh?

Related Topics
org.w3c.dom should be deprecated
XML to POJOs project is in the air

3 Comments:

At 12/14/2005 11:38:00 PM, Anonymous Anonymous said...

Why not pass an actual factory instance to the enum instances instead of only the class?

 
At 12/15/2005 04:02:00 AM, Blogger Avah said...

Fine question.

Obviously, it Can be done - I just wanted to avoid writing many classes. Obviously, one could write a generified class HandlerFactory (typed T) which performs "return new T()".

Specifically for my case it was more difficult to do - I had different parameters and caches of handlers that I wanted more control over than in the static methods of Enum, but indeed if I didn't, your solution would have been the better-looking one!

Thank you annonymous! :)

 
At 12/15/2005 08:58:00 PM, Anonymous Anonymous said...

You're welcome :)

 

Post a Comment

<< Home