Mutant World

Sunday, April 24, 2005

Enums as factories

I started to enjoy very much J2SE 5, especially generics, enums and the java.util.concurrent package.

I still don't get static imports, but overall J2SE 5 is been a good experience.

One thing I found nice about enums is the possibility to use them as factories in a simple way.

For example, Webwork 2 can be configured to use 3 different multipart parsers.
The configuration option is called webwork.multipart.parser and can have one of 3 possible values: pell, jakarta or cos.
The 3 implementation classes extends the class com.opensymphony.webwork.dispatcher.multipart.MultiPartRequest so it's possible to write the following enum:

public enum MultipartParsers

private final Class<? extends MultiPartRequest> parserClass;

private MultipartParser(Class<? extends MultiPartRequest> parserClass)
this.parserClass = parserClass;

public MultiPartRequest newInstance()
return parserClass.newInstance();

Using this class is very simple, given the following configuration:


A Configuration class can read the configuration, and creating the multipart parser is then very easy:

String parser = Configuration.getString("webwork.multipart.parser");
MultiPartRequest multipart = MultiPartParsers.valueOf(parser.toUpperCase()).newInstance();

Note the MultiPartParsers.valueOf() method, which is generated by the compiler for each enum class: it takes a string and returns the enum instance whose name matches the string.
Using MultiPartParsers.valueOf() avoid switch statements or chained if/else statements.
The possibility to use more verbose values (like 'pell' or 'jakarta') is definitely more appealing than using integer values (like '1' or '2') to distinguish parsers.

I have used this pattern also for commands, and the newInstance() method can take parameters to initialize the newly created instance, or even a vararg parameters.

public enum Commands

private final Class<? extends Command> commandClass;

private MultipartParser(Class<? extends Command> commandClass)
this.commandClass = commandClass;

public Command newInstance(Configuration config)
Command command = commandClass.newInstance();
return command;