У моих коллег и меня было обсуждение относительно логики в перечислениях. Мое персональное предпочтение не состоит в том, чтобы иметь никакого вида логики в перечислениях Java (хотя Java обеспечивает способность сделать это). Обсуждение в этом случилось центрируемый вокруг наличия удобного метода в перечислении, которое возвратило карту:
public enum PackageType {
Letter("01", "Letter"),
..
..
Tube("02", "Packaging Tube");
private String packageCode;
private String packageDescription;
..
..
public static Map<String, String> toMap() {
Map<String, String> map = new LinkedHashMap<String, String>();
for(PackageType packageType : PackageType.values()) {
map.put(packageType.getPackageCode(), packageType.getPackageDescription());
}
return map;
}
}
Мое персональное предпочтение состоит в том, чтобы вытащить это на службу. Аргумент в пользу того, чтобы иметь метод в перечислении, центрируемом вокруг удобства. Идея состояла в том, что Вы не должны переходить к службе для получения его, но можете запросить перечисление непосредственно.
Мой аргумент, центрируемый вокруг разделения беспокойства и абстрагирующий любой вид логики к сервису. Я не думал, что "удобство" было веским доводом для помещения этого метода в перечислении.
С точки зрения лучших практик, какой лучше? Или это просто сводится к вопросу персонального предпочтения и стиля кода?
Что ж, я делал это раньше, но это, конечно, не значит, что это «лучший» поступок.
Однако, с моей точки зрения, я бы предпочел иметь эту логику в перечислении по той же причине, по которой вы не переместите метод toString в службу. Логика касается только самого перечисления и его собственного представления.
Я думаю, что было бы ошибкой переносить такой метод в службу - помещая его в перечисление, вы заранее заявляете о том, что перечисление имеет метод toMap. Кто-то, кто не знал об услуге и просто смотрел на enum, может этого не знать.
Это также помогает с автоматическим завершением в IDE - я могу нажать "." key и мгновенно увидеть методы, предоставляемые объектом.
Я думаю, что это, вероятно, сводится к личным предпочтениям и тому, думаешь ли ты, что логика может измениться в будущем.
Лучше всего использовать логику перечисления (поскольку она довольно статична) для вещей, которые не собираются меняться. Логика в java.util.concurrent.TimeUnit
является довольно хорошим примером: коэффициенты преобразования между единицами времени четко определены и никогда не изменятся, так что это хороший кандидат для статической логики. встроен в перечисление.
Я бы начал с помещения его в перечисление. Если в системе будет только один метод toMap (), наличие дополнительного класса, безусловно, излишне и будет раздражать.
Если бы у меня была куча перечислений, из которых я хочу создать такую карту или, возможно, предвидеть такую ситуацию, ТОГДА я создам статический служебный класс и обобщенный служебный метод для этого.
Мое личное мнение, практичность бродит по теории.
РЕДАКТИРОВАТЬ: Ой, подождите, было бы сложно предоставить универсальный служебный метод для .. В этом случае, если метод будет специфичным для этого перечисления, я бы определенно пошел и поместил его в перечисление. Если бы я был программистом по обслуживанию, я был бы очень недоволен, если бы у вас был дополнительный класс, который мне пришлось бы искать.
Как и все остальное, это зависит от использования, есть общие правила, но практичность всегда должна побеждать в споре. Для чего используется карта? Нужно ли вам когда-нибудь ограничить содержимое карты, например, если карта используется для заполнения комбинированного поля, есть ли необходимость удалить некоторые варианты, скажем, если некоторые перевозчики работают только с определенными типами пакетов, можно использовать стратегию для заполнения карты, что лучше всего сделать вне перечисления.
Несмотря на это, я бы предпочел, чтобы карта создавалась в другом месте, этот дополнительный уровень непрямолинейности никогда не мешает гибкости и может сэкономить много хлопот, а сейчас добавляет мало накладных расходов. И вы также можете написать код так, чтобы получить аналогичную функциональность с другими перечислениями.
Я несколько раз пробовал логику в перечислениях, но единственное, что меня действительно радует, это что-то вроде:
// not compiled, so might have errors...
public enum Foo
{
A,
B;
// not complete, doesn't properly handle invalid cases...
public static Foo fromString(final String str)
{
final String strLower;
final Foo val;
strLower = str.toLowerCase();
if(strLower.equals("a")
{
val = A;
}
else if(strLower.equals("b")
{
val = B;
}
else
{
throw new IllegalArgumentException(/*...*/);
}
return (val);
}
}
Вообще, как только вы начинаете добавлять переменные/методы экземпляра, вы, вероятно, должны делать что-то с помощью соответствующего класса.
Я не вижу убедительной причины, почему это "хорошая практика" ... или "плохая практика" ... делать то, что вы предлагаете.
Я склоняюсь к аргументу удобства. Но, честно говоря, это не та вещь, на которую продуктивно тратить человеко-дни на обсуждение ... ИМО.