Ответ 1
Если это универсальная утилита, static - это ИМО лучше. Вы заявили, что у вас не будет каких-либо штатов для хранения, поэтому я не понимаю, почему вы должны сделать это не статическим. Если объявить его статичным, он также сохранит память.
Если мне нужно создать класс Утилиты (например, ByteUtils или StreamUtils или StringUtils), какой лучший выбор для них.
PS: По статическому классу я имел в виду класс со статическими методами (а не внутренний статический класс)
Пожалуйста, дайте советы по выбору дизайна для этого?
Если это универсальная утилита, static - это ИМО лучше. Вы заявили, что у вас не будет каких-либо штатов для хранения, поэтому я не понимаю, почему вы должны сделать это не статическим. Если объявить его статичным, он также сохранит память.
Мои классы утилиты выглядят следующим образом:
// final, because it not supposed to be subclassed
public final class FooUtil {
// private constructor to avoid unnecessary instantiation of the class
private FooUtil() {
}
public static int doSomethingUseful() {
}
// ...
}
Обратите внимание, что хотя это делает методы утилиты легко проверяемыми и легкодоступными извне, это также делает классы, использующие их жесткими для модульного тестирования, потому что нелегко издеваться над этими методами утилиты. Слишком много таких классов полезности может быть признаком отсутствия дизайна OO (процедурное программирование) и может действительно сделать код трудным для тестирования.
Если вы используете инфраструктуру инъекций зависимостей (Spring, Guice, что угодно), может быть хорошей идеей просто сделать класс утилиты интуитивным, с нестационарными методами и сделать его инъекционным синглтоном. Таким образом, классы, использующие эти методы, могут быть протестированы путем издевательства над объектом утилиты.
Просто потому, что что-то может быть статическим, не означает, что он должен быть статическим.
Во всем этом есть еще одно соображение: насмешка. Труднее издеваться над статическими методами в ваших тестах, чем издеваться над поведением экземпляра класса.
Разговор о ненужных распределениях кучи и GCing объектов приносит мне преждевременную оптимизацию. JVM будет неплохо работать над оптимизацией этой проблемы.
Самый простой способ определить класс Utility - это перечисление без экземпляров
public enum Utility {;
public static int utilityMethod(int x) { /* ... */ }
}
Класс утилиты не должен иметь никакого состояния или иметь минимальное состояние, поэтому вы не должны беспокоиться о GC.
У вас могут быть другие классы с сохранением состояния для конкретных целей, таких как Builder, Factory, вы можете создать объект по своему желанию и отменить его, когда закончите.
Хорошо сделать класс нестационарным с помощью частного конструктора:
Обычно классы полезности содержат статические методы и атрибуты, этот подход упрощает использование своих методов без создания экземпляра класса. Надеюсь, это поможет.
Чистые классы полезности обычно должны быть статическими. Когда у вас есть класс с четко определенным вводом и выводом, никаких побочных эффектов и никакого состояния, то по определению он должен быть статическим классом.
В общем, не добавляйте сложность (инъекция зависимостей в этом случае) до того, как она понадобится, и приложите себе пользу.
Если вы можете сделать их статичными, то обязательно сделайте это!
Другими словами, если они не имеют состояния, они должны быть статическими.
Хорошо, если у вас нет состояния для хранения, тогда GC не существует, поэтому я бы пошел со статикой, таким образом вы избегаете ненужных распределений кучи и GC.
Никто здесь не упоминает, что статические методы утилиты не расширяемы. Вы не можете их переопределить. Вы не можете воспользоваться ООП (в частности, полиморфизм, который является самой мощной функцией ООП). Это приводит к дублированию кода.
P.S. Я нашел эту статью очень полезной. http://www.yegor256.com/2014/05/05/oop-alternative-to-utility-classes.html