Я искал вокруг в течение многих дней для нахождения ответа на эту основанную на производительности проблему.
После рытья Интернета до сих пор я узнал, что существует несколько способов использовать Перечисления в Java, хорошо зарегистрированном в здесь. Ну, определенно как начинающий можно было бы хотеть Перечисления использования в операторе case оператора switch, который обеспечивает ясность и лучшее понимание кода. Но с другой стороны у нас есть реализация стиля Шаблона "посетитель" Перечислений также, которая гарантирует безопасность типов и расширяемость, Обсужденную здесь.
Однако и возвращаясь к исходной идее позади этого вопроса, до сих пор я узнал, что, если конструкция случая переключателя правильно разработана с помощью Перечислений, который гарантирует, что значения случая не редки, и что Перечислимое объявление находится в той же единице компиляции как оператор case оператора switch, компилятор Java выполняет некоторую оптимизацию на произведенном байт-коде путем реализации такой конструкции как Таблица переходов (обсужденный в здесь и в другом месте также на веб-сайте Sun, которому я потерял ссылку). Теперь, это определенно окрыляет производительность по сравнению с несколькими/вкладывать если еще конструкция.
Мой вопрос, как Java реализует основанную на шаблоне "посетитель" реализацию Перечислений в получающемся байт-коде и каково повышение производительности в то время как по сравнению с основанной на случае переключателя реализацией, если таковые имеются?
И какой тип реализации должен, я предпочитаю, полагая, что мои Перечисления могут вырасти в будущем, и я увлечен производительностью также. В настоящее время у меня есть приблизительно 19 и нечетные константы в моем Перечислении.
Править
У меня есть класс, который хранит некоторую информацию о переменных игры. Одна из переменных, являющихся Перечислимым типом.
public class GameObject {
private Shape mShape;
public Shape getShape() {
return mShape;
}
.
.
.
public static enum Shape {
SHAPE1, SHAPE2, SHAPE3, SHAPE4, ..., SHAPE20
};
public void drawShape() {
switch (this.mShape) {
case SHAPE1:
drawShape1();
break;
case SHAPE2:
drawShape2();
break;
case SHAPE3:
drawShape3();
break;
case SHAPE4:
drawShape4();
break;
.
.
.
.
.
case SHAPE20:
drawShape20();
break;
default:
drawUnknown();
break;
}
}
}
Позже я понял разделения информации от логики, и следовательно создал другой класс и переместил Перечислимую Форму от GameObject до этого нового класса GraphicModel, и вместо того, чтобы иметь случай переключателя там, я реализовал постоянно-определенные методы. И да я действительно помещал надлежащих операторов импорта в любой класс после этой модификации.
public class GraphicModel {
public void drawGraphicFromObject(GameObject gameObject) {
gameObject.getShape().draw();
}
public static enum Shape {
// This method is not public, instead is only called by GraphicModel
abstract void draw();
SHAPE1 {
@Override
void draw() {
// some transformations
}
},
SHAPE2 {
@Override
void draw() {
// Some different transformation
}
},
SHAPE3 {
@Override
void draw() {
// Yet another transform
}
},
.
.
.
.
UNKNOWN {
@Override
void draw() {
//
}
};
}
}
Позже я даже реализовал это на основе шаблона "посетитель", как предложено здесь
Так, что я должен знать, это, какой способ реализации более эффективен? Определенно, чтобы случай переключателя был преобразован в таблицы переходов на компиляции, Java требует и перечислимого объявления и операторов переключения в той же единице компиляции. Я должен использовать основанную на переключателе реализацию или постоянно-определенную реализацию метода в моем классе GraphicModel? Скорее чтобы быть ясным, какова разница в производительности?
Enums, вообще говоря, сопоставимы по производительности с int константами, если они используются в выражении switch (1).
Может быть, Вам лучше рассмотреть что-нибудь по аналогии с реализацией констант конкретного метода , например,
public enum Mode {
ON { Color color() {return Color.GREEN;}},
OFF { Color color() {return Color.RED;}},
STANDBY { Color color() {return Color.YELLOW;}},
DEFAULT { Color color() {return Color.BLACK;}};
abstract Color color();
}//enum Mode
, а затем использовать
getMode().color();
вместо оператора switch?!
Однако, я думаю, что для "получить только цветной случай", возможно, методы вообще не нужны.
В общем, я настоятельно рекомендую вам Эффективную Java для вашей книжной полки. В главе 6 будет обсуждаться Enums and Annotations.