Enum constant specific initialization

221 Views Asked by At

Now, we all know that an enum is a great way to do multitons (ie. a class which has a fixed number of instances, known at compile-time), as each constant is pretty much a singleton subclass of your own enum class. However, I've run into a problem of how to make an enum constant specific initialization.

Suppose we have the following enum:

public enum InputMethod {
    FOO {
        private final FooFactory factory;

        public Document createDocument(String inputString) {
            return factory.createFooParser().parse(inputString);
        }
    },
    BAR {
        public Document createDocument(String inputString) {
            BarBuilder builder = new BarBuilder();
            builder.setInput(inputString);
            return input.build();
        }
    };

    public abstract Document createDocument(String inputString);
}

What I want to do is initialize the FooFactory instance in InputMethod.FOO. And in order to do so, I would have to call, say, FooFactory.newInstance(). However, this may throw an exception, so I cannot simply say factory = FooFactory.newInstance() directly. I cannot put this in the enum type's constructor, since InputMethod.BAR doesn't make use of FooFactory in any way. It would appear that using static initialization doesn't work due to the order in which static initialization is done relative to the initialization of the enum constants itself. Finally, I cannot explicitly declare a constructor, since the subclass of InputMethod that FOO is an instance of just happens to be anonymous.

So, other than resigning myself to lazy initialization, how would I properly initialize the FooFactory instance in InputMethod.FOO?

1

There are 1 best solutions below

0
On
public enum InputMethod {
    FOO {
        private final FooFactory factory;
        {
            try {
                factory = Factory.newInstance();
            } catch (...) {
                ...
            }
        }
        public Document createDocument(String inputString) {
            return factory.createFooParser().parse(inputString);
        }
    },
    BAR { ... };
    public abstract Document createDocument(String inputString);
}