如何在枚举中定义通用成员变量?

时间:2011-06-01 16:34:28

标签: java generics enums

我想引用一个枚举方法来检索算法的类,以便我可以延迟加载算法的新实例,以便在策略设计模式中使用。

在这个例子中,我使用枚举来引用计算Fibonacci数的三个不同策略类:RecursiveFibonacciGeneratorIterativeFibonacciGeneratorMemoizedFibonacciGenerator(所有这些都继承自{{1} }})。

代码(生成错误的行用意图评论)如下:

FibonacciGenerator

我想知道如何使用此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"); } } 构造函数来存储enum类型的成员变量。

修改:添加完整代码以澄清意图

5 个答案:

答案 0 :(得分:6)

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;
    }
}

这样做你想要的吗?

另一种选择是使用该类的实例,但经过进一步思考后我认为这是一个坏主意。如果您打算使用该类的实例,那么为什么您首先需要枚举?

答案 1 :(得分:1)

尝试提供真实实例而不是类:

public enum Algorithm {
    RECURSIVE (new RecursiveFibonacciGenerator()),
    ITERATIVE (new IterativeFibonacciGenerator()),
    MEMOIZED (new MemoizedFibonacciGenerator());

    private <T extends FibonacciGenerator> Algorithm(T algorithm) {}
}

答案 2 :(得分:1)

Plouh是对的。你可以声明并初始化一个成员变量,就好像它是一个类而不是一个枚举:

private final FibonacciGenerator _instance;

private Algorithm(FibonacciGenerator instance) {
    _instance = instance;
}

然后通过公共getFibonacciGenerator()方法返回它。请注意,如果存储实例而不是Class,则无需使用泛型。并记得将该字段声明为“最终”

答案 3 :(得分:0)

我不确定我是否理解这个问题,但如果您只是想将策略保留为成员变量:

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

  private Class<? extends FibonacciGenerator> strategy;

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

  Class<? extends FibonacciGenerator> getStrategy() {
    return strategy;
  }
}

答案 4 :(得分:0)

我最终得到了以下代码:

package com.example.strategy;

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

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

        public FibonacciGenerator getInstance() {
            if (this.instance == null) {
                try {
                    this.instance = this.algorithmClass.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return this.instance;
        }
    }

    public Integer getTerm(Integer termNumber) {
        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");
        return term;
    }
}