Это плохая практика для класса иметь только статические поля и методы?

У меня есть класс, который состоит только из статических переменных-членов и статических методов. По сути, он служит служебным классом общего назначения.

Плохо ли для класса содержать только статические переменные-члены и статические методы?

15 ответов

Решение

Нет, я так не думаю. Хуже практики иметь класс, полный методов экземпляра, которые на самом деле не зависят от конкретного экземпляра. Сделав их статичными, пользователь точно узнает, как они предназначены для использования. Кроме того, вы избегаете ненужных реализаций таким образом.

РЕДАКТИРОВАТЬ: В качестве запоздалой мысли, в общем, я думаю, что это хорошо, чтобы избежать использования языковых функций "просто потому что", или потому что вы думаете, что это "способ Java сделать это". Я вспоминаю свою первую работу, где у меня был класс, полный статических утилитарных методов, и один из старших программистов сказал мне, что я не полностью использую силу ОО Java, сделав все свои методы "глобальными". Она не была в команде 6 месяцев спустя.

Пока класс не имеет внутреннего состояния и по существу является так называемым конечным классом (вспомогательные классы попадают в эту категорию), другими словами, он не зависит от других классов. Это хорошо.

Math класс является ярким примером.

Звучит разумно.

Примечание. Классы, которые делают это, часто имеют собственный конструктор без аргументов, так что компилятор выдает ошибку, если программист пытается создать экземпляр статического класса.

Статические методы меня не сильно волнуют (кроме тестирования).

В целом, статические члены являются проблемой. Например, что если ваше приложение кластеризовано? Как насчет времени запуска - какая инициализация происходит? Для рассмотрения этих вопросов и многое другое, прочитайте эту статью Гилада Брача.

Это совершенно разумно. Фактически, в C# вы можете определить класс с ключевым словом static специально для этой цели.

Только не увлекайся этим. Обратите внимание, что класс java.lang.Math предназначен только для математических функций. У вас также может быть класс StringUtilities, который содержит общие функции обработки строк, которых нет, например, в стандартном API. Но если ваш класс называется Utilities, например, это подсказка, что вы можете разделить его.

Также обратите внимание, что Java специально ввел статический импорт: ( http://en.wikipedia.org/wiki/Static_import)

Статический импорт - это функция, представленная в языке программирования Java, члены (поля и методы) которой определены в классе как общедоступные статические для использования в коде Java без указания класса, в котором определено поле. Эта функция была введена в язык в версии 5.0.

Эта функция обеспечивает типобезопасный механизм для включения констант в код без ссылки на класс, который первоначально определил поле. Это также помогает отказаться от практики создания постоянного интерфейса: интерфейса, который определяет только константы, а затем пишет класс, реализующий этот интерфейс, что считается нецелесообразным использованием интерфейсов [1].

Механизм может быть использован для ссылки на отдельных членов класса:

 import static java.lang.Math.PI;
 import static java.lang.Math.pow;

или все статические члены класса:

 import static java.lang.Math.*;

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

Пока вы об этом подумали, я не вижу проблем с вашим решением.

Согласно жесткой интерпретации объектно-ориентированного проектирования, служебный класс - это то, чего следует избегать.

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

Даже Java-дизайнеры создают служебные классы (на ум приходит java.lang.Math)

Ваши варианты:

double distance = Math.sqrt(x*x + y*y);  //using static utility class

против:

RootCalculator mySquareRooter = new SquareRootCalculator();
mySquareRooter.setValueToRoot(x*x + y*y);
double distance;
try{
   distance = mySquareRooter.getRoot();
}
catch InvalidParameterException ......yadda yadda yadda.      

Даже если бы мы избегали многословного метода, мы все равно могли бы получить:

Mathemetician myMathD00d = new Mathemetician()
double distance = myMathD00d.sqrt(...);

в этом случае.sqrt() все еще статичен, так какой смысл в создании объекта в первую очередь?

Ответ таков: создавайте служебные классы, когда вы можете создать искусственный класс "Рабочий", который не имеет или почти не использует переменные экземпляра.

Эта ссылка http://java.dzone.com/articles/why-static-bad-and-how-avoid видимому, противоречит большинству ответов здесь. Даже если он не содержит переменных-членов (т. Е. Нет состояния), статический класс все равно может быть плохой идеей, потому что он не может быть смоделирован или расширен (разделен на подклассы), поэтому он побеждает некоторые принципы ОО

Служебные методы часто размещаются в классах с использованием только статических методов (например, StringUtils.) Глобальные константы также помещаются в их собственный класс, чтобы их можно было импортировать остальной частью кода (public final static атрибутов.)

Оба использования довольно распространены и имеют частные конструкторы по умолчанию, чтобы предотвратить их создание. Объявление класса final предотвращает ошибку при попытке переопределить статические методы.

Если по static member variables вы не имели в виду глобальные константы, возможно, вы захотите поместить методы, обращающиеся к этим переменным, в свой собственный класс. В таком случае, не могли бы вы рассказать о том, что эти переменные делают в вашем коде?

Обычно так устроены служебные классы, и в этом нет ничего плохого. Известные примеры включают o.a.c.l.StringUtils, o.a.c.d.DbUtils, o.s.w.b.ServletRequestUtils, так далее.

Класс Collections в Java SDK имеет только статические члены.

Итак, вы идете, если у вас есть надлежащее обоснование - это не плохой дизайн

Из документов TSLint:

Пользователи, пришедшие из объектно-ориентированного языка в стиле Java, могут заключить свои служебные функции в дополнительный класс вместо того, чтобы помещать их на верхний уровень.

Лучше всего использовать константу, например:

      export const Util = {
    print (data: string): void {
        console.log(data)
    }
}

Примеры неправильного кода для этого правила:

      class EmptyClass {}

class ConstructorOnly {
  constructor() {
    foo();
  }
}

// Use an object instead:
class StaticOnly {
  static version = 42;
  static hello() {
    console.log('Hello, world!');
  }
}

Примеры правильного кода для этого правила:

      class EmptyClass extends SuperClass {}

class ParameterProperties {
  constructor(public name: string) {}
}

const StaticOnly = {
  version: 42,
  hello() {
    console.log('Hello, world!');
  },
};

Я не буду беспокоиться о служебном классе, содержащем статические методы.

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

Другие вопросы по тегам