Подтвердить что ты не робот

Java 8: интерфейс со статическими методами вместо статического класса util

Что является лучшей практикой в ​​Java 8, когда мне нужна куча устаревших методов утилиты. Правильно ли иметь интерфейс, который будет not реализован кем-либо, т.е. public interface Signatures и public interface Environments, или лучше сделать это по-старому - иметь public final class Signatures и public final class Environments с частные конструкторы || перечисления?

4b9b3361

Ответ 1

Основная цель интерфейсов - предоставить тип и словарь операций (методов) этого типа. Они полезны и гибки, потому что они допускают множество реализаций, и действительно, они предназначены для реализации реализаций, которые иначе не связаны в иерархии классов.

Вопрос спрашивает,

Правильно ли иметь интерфейс, который не будет реализован кем-либо...?

Мне кажется, что я режу против зерна интерфейсов. Нужно было бы осмотреть API, чтобы определить, что нет классов, которые реализуют этот интерфейс, и что нет производителей или потребителей этого интерфейса. Кто-то может быть смущен и попытаться создать реализацию интерфейса, но, конечно, они не уйдут далеко. В то время как возможно иметь "служебный интерфейс" со всеми статическими методами, это не так ясно, как старый неконструктивный конечный класс идиомы. Преимущество последнего заключается в том, что класс может обеспечить, чтобы никакие экземпляры никогда не могли быть созданы.

Если вы посмотрите на новые API-интерфейсы Java 8, вы увидите, что идиома последнего класса по-прежнему используется, несмотря на возможность добавления статических методов на интерфейсы.

Статические методы на интерфейсах использовались для таких вещей, как методы factory для создания экземпляров этих интерфейсов или для методов полезности, которые имеют общую применимость во всех экземплярах этих интерфейсов. Например, см. Интерфейсы Stream и Collector в java.util.stream. Каждый из них имеет статические фабрики: Stream.of(), Stream.empty() и Collector.of().

Но также обратите внимание, что у каждого есть классы вспомогательной утилиты StreamSupport и Collectors. Это чистые классы полезности, содержащие только статические методы. Возможно, они могут быть объединены в соответствующие интерфейсы, но это загромождает интерфейсы и размывает взаимосвязь методов, содержащихся в классах. Например, StreamSupport содержит семейство связанных статических методов, которые являются всеми адаптерами между Spliterator и Stream. Объединение их в Stream, вероятно, сбивает с толку.

Ответ 2

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

Ответ 3

Статические методы в интерфейсах были добавлены с двумя основными целями:

  • В случае плохой реализации в подклассах статические методы интерфейса могут использоваться для обеспечения проверок (например, если значение равно null).

  • Избегайте использования общих классов утилиты (например, Collections) и вызова статических методов через их надлежащий интерфейс.

Итак, это очень хорошая практика, если вы намерены использовать функциональные возможности для соответствующих классов.

update:

Если вы хотите создать чистую коллекцию функций, вы можете использовать абстрактный класс со статическими методами и частный конструктор.

Ответ 4

В хорошем объектно-ориентированном дизайне не так много (если есть) методов утилиты без сохранения.

Лучшей техникой, с которой я столкнулся, является использование состояния (объектов) для работы с этой функцией.

Итак, вместо того, чтобы делать

 Temperature.farenheitFromCelcius(...);

Я делаю

 public class FarenheitFromCelcius implements Function<Celcius, Farenheit> {

    public Farenheit apply(Celcius celcius) {
      return new Farenheit(5 * celcius.getValue() / 9 + 32);
    }

 }

Это имеет несколько преимуществ. Одно из них заключается в том, что его можно легко выгружать из памяти. Другое из того, что вы можете сэкономить на количестве интерфейсов идентификации типов, вы можете передавать методы утилиты между методами, а конечным является то, что вы можете использовать иерархию типов Java.

Затраты минимальны. В основном вам нужно изменить способ применения метода.

 public <T> R convertTemp(T temp, Function<T, R> conversion) {
   return conversion.apply(temp);
 }

Естественно, вы никогда не напишете полный метод для инкапсуляции объектно-ориентированной функции, но мне пришлось показать пример...