Как определить универсальную переменную-член в перечислении? - PullRequest
3 голосов
/ 01 июня 2011

Я хочу сослаться на метод enum для получения класса алгоритма, чтобы я мог лениво загрузить новый экземпляр алгоритма для использования в шаблоне разработки стратегии.

В этом примере яиспользование перечисления для ссылки на три различных класса стратегии, которые вычисляют числа Фибоначчи: RecursiveFibonacciGenerator, IterativeFibonacciGenerator и MemoizedFibonacciGenerator (все они наследуются от 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 для хранения переменной-члена типа Class<T>.

Редактировать: Добавлен полный код для уточнения намерений

Ответы [ 5 ]

6 голосов
/ 01 июня 2011
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 голос
/ 01 июня 2011

Плух прав. И вы можете объявить и инициализировать переменную-член так же, как если бы это был класс, а не перечисление:

private final FibonacciGenerator _instance;

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

, а затем вернуть его через публичный метод getFibonacciGenerator (). Обратите внимание, что нет необходимости использовать дженерики, если вы храните экземпляр, а не класс. И не забудьте объявить поле как «окончательное»

1 голос
/ 01 июня 2011

Попробуйте предоставить реальный экземпляр вместо класса:

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

    private <T extends FibonacciGenerator> Algorithm(T algorithm) {}
}
0 голосов
/ 01 июня 2011

Я получил следующий код:

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;
    }
}
0 голосов
/ 01 июня 2011

Я не уверен, хорошо ли я понимаю вопрос, но если вы просто хотите сохранить стратегию в качестве переменной-члена:

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;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...