У меня есть служебный класс, который содержит статическую конечную карту с некоторыми значениями. Мне нужен доступ к этой карте в другом классе. Должен ли я просто объявить карту общедоступной или мне следует написать геттер внутри служебного класса и, следовательно, сделать карту частной?
Оба способа работают, но каковы наилучшие методы?
public MyUtilityClass {
public static final Map<String, Integer> MAX_LENGTHS = ImmutableMap.of(
"title", 256,
"text", 512);
}
public MyAnotherClass {
public void someMethod() {
//accessing the map directly
MAX_LENGTHS.get("title")
}
}
Или
public MyUtilityClass {
private static final Map<String, Integer> MAX_LENGTHS = ImmutableMap.of(
"title", 256,
"text", 512);
public static final getMaxLengthMap() {return MAX_LENGTHS;}
}
public MyAnotherClass {
public void someMethod() {
//accessing the map directly
getMaxLengthMap().get("title")
}
}
Ну, на самом деле ключи являются значениями перечисления. Что-то типа :
private static final Map<String, Integer> MAX_LENGTHS = ImmutableMap.of(
MyEnumClass.TITLE, 256,
MyEnumClass.TEXT, 512);
Вы используете проект ImmutableMap
from guava
; таким образом, неизменяемый истинныйMap
.
Сделать это public
никому не повредит, так как никто не может изменить это Map
каким-либо образом.
Геттер ничего не добавляет - я бы просто оставил его общедоступным.
Что может иметь смысл, так это иметь метод, который возвращает значение напрямую:
public MyUtilityClass {
private static final Map<String, Integer> MAX_LENGTHS = ImmutableMap.of(
"title", 256,
"text", 512);
public static final getMaxLength(String item) {return MAX_LENGTHS.get(item);}
}
public MyAnotherClass {
public void someMethod() {
//accessing the map directly
getMaxLength("title");
}
}
Это также позволяет вам легко изменить базовую реализацию позже. Например, вы можете вернуть значение по умолчанию для элементов, которых нет на карте и т. д.
Вы собираетесь засорять этот служебный класс методами Map
... Завтра я захочу containsKey
от MAX_LENGTHS
, что мне делать?
Это также правильный путь при определении пользовательских функций сопоставления в перечислениях, поскольку valueOf
выдает неправильные имена.
@AndrewTobilko добавьте еще один метод. Это не мусорить. Рассмотрите возможность перечисления (если вам нужно перечислить значения) или используйте несколько вспомогательных классов.
@roookeee Я думаю, что это ... Вы собираетесь написать кучу методов Map только для резервного копирования частного поля один. Что, если бы у класса были другие поля/методы, не связанные с Map (что весьма вероятно для служебного класса)? (Раньше я использовал этот подход, теперь я не нахожу в нем ничего хорошего)
«Это также позволяет вам легко изменить базовую реализацию позже». Мне интересно, насколько это важно... Это служебный класс, используемый внутри компании, и он не будет выставлен на всеобщее обозрение, верно?
@AndrewTobilko Я не говорю, что это нужно делать именно так - я просто даю ОП еще один вариант. Основываясь на этом простом примере, я согласен с тем, что общедоступное поле совершенно нормально.
@assylias да, это хороший момент. Мне нужно подумать, нужно ли мне возвращать значение по умолчанию или нет. Если мне это не нужно, я просто позволю ему быть общедоступным, поскольку он неизменяем.
Я бы всегда выбирал реализацию, которая предоставляет только необходимые данные. Я бы позволил вспомогательной функции вернуть Optional
, поскольку не все возможные String
отображаются, что уже предлагает применение дополнительной резервной логики без раскрытия внутренней структуры данных.
Это зависит от того, что вам нужно сделать с вашей картой. Предоставление доступа к ней непосредственно на карту (чтобы установить ее как общедоступную) даст любому возможность использовать и изменять эту карту без каких-либо ограничений.
В вашем случае карта является окончательной и неизменной, поэтому это не применимо.
Но если вы хотите ограничить этот доступ только некоторым его содержимым, например title
, то правильным выбором будет создание метода, который будет возвращать только String
.
Установка карты как общедоступной или создание метода, который возвращает всю карту, не имеет значения.
Карта неизменна, поэтому ваши первые баллы не применяются.
@Leviand изменять эту карту без каких-либо ограничений не для карты, которую использует OP.
Вы правы, я исправил свой ответ
Я думаю, что добавление геттера в класс-владелец было бы правильным.
public MyUtilityClass {
private static final Map<String, Integer> MAX_LENGTHS = ImmutableMap.of(
"title", 256,
"text", 512);
public static int getLength(final String key) {
return MAX_LENGTHS.get(key);
}
}
public MyAnotherClass {
public void someMethod() {
int x= MyUtilityClass.getLength("title")
}
}
Это изолирует MyAnotherClass
от необходимости знать какие-либо детали реализации геттера и значительно упрощает создание макетов для тестирования.
Я должен сказать, что вам, вероятно, лучше использовать Enum
в первую очередь. Поскольку это сопоставление кажется всегда полностью статичным:
public enum MaxLength {
TITLE(256),
TEXT(512);
public final int value;
MaxLength(int value) {
this.value= value;
}
}
Больше нет необходимости в этом служебном классе, теперь вы можете просто получить значение напрямую:
int length = MaxLength.TITLE.value;
«Геттер» на
MyUtilityClass
, вероятно, должен возвращать значение ключа, а не пользователям класса, которые должны знать, что это за ключи или как они хранятся.