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?