How do I define a generic member variable in an enum?

I want to reference an enum method to retrieve the class of an algorithm so that I can lazy-load a new instance of the algorithm for use in the strategy design pattern.

In this example, I am using an enum to reference three different strategy classes that calculate Fibonacci numbers: RecursiveFibonacciGenerator, IterativeFibonacciGenerator, and MemoizedFibonacciGenerator (all of which inherit from FibonacciGenerator).

The code (with lines generating errors commented with intent) is as follows:

package com.example.strategy;

public class Fibonacci {
    private enum Algorithm {
        RECURSIVE (RecursiveFibonacciGenerator.class),
        ITERATIVE (IterativeFibonacciGenerator.class),
        MEMOIZED (MemoizedFibonacciGenerator.class);

        private final Class<T> algorithmClass; // Declare class of same type as constructor
        private final T instance; // Declare instance of class defined in constructor
        private <T extends FibonacciGenerator> Algorithm(Class<T> algorithmClass) {
            this.algorithmClass = algorithmClass;
        }

        public T getInstance() {
            if (this.instance == null) {
                this.instance = this.algorithmClass.newInstance();
            }
            return this.instance;
        }
    }

    public Integer getTerm(Integer termNumber) {
        profileGenerator(termNumber, Algorithm.RECURSIVE);
        profileGenerator(termNumber, Algorithm.ITERATIVE);
        return profileGenerator(termNumber, Algorithm.MEMOIZED);
    }

    private Integer profileGenerator(Integer termNumber, Algorithm algorithm) {
        System.out.print("Computing term using " + algorithm.toString() + " algorithm... ");
        Long startTimeMilliseconds = System.currentTimeMillis();
        Integer term = algorithm.getInstance().generateTerm(termNumber);
        Long endTimeMilliseconds = System.currentTimeMillis();
        Long computationTimeMilliseconds = endTimeMilliseconds - startTimeMilliseconds;
        System.out.println("term computed in " + computationTimeMilliseconds + " milliseconds");
    }
}

I would like to know how I can use this enum constructor to store a member variable of the Class<T> type.

Edit: Added full code to clarify intent

Answer

public enum Algorithm {
    RECURSIVE(FibonacciGenerator.RecursiveFibonacciGenerator.class),
    ITERATIVE(FibonacciGenerator.IterativeFibonacciGenerator.class),
    MEMOIZED(FibonacciGenerator.MemoizedFibonacciGenerator.class);

    private final Class<? extends FibonacciGenerator> algorithmClass;

    private <T extends FibonacciGenerator> Algorithm(Class<T> algorithmClass) {
        this.algorithmClass = algorithmClass;
    }
}

Does that do what you want?

The other option is to use an instance of the class, but after further thought I think this is a bad idea. If you are going to use an instance of the class then why’d you need the enum in the first place?

Leave a Reply

Your email address will not be published. Required fields are marked *