Постоянный интерфейс - Constant interface

в Язык программирования Java, то постоянный интерфейс шаблон описывает использование интерфейс исключительно для определения констант и имея классы реализовать этот интерфейс для обеспечения удобного синтаксического доступа к этим константам. Однако, поскольку константы очень часто являются просто деталью реализации, а интерфейсы, реализованные классом, являются частью его экспортируемого API, эта практика сводится к помещению деталей реализации в API , что было сочтено неуместным, например, разработчиком Java Джошуа Блох.[1] В общем, сбор системных констант в классы, независимые от поведения, может создать плохой объектно-ориентированный дизайн, потому что это часто является признаком низкого сплоченность. По этим причинам постоянные интерфейсы можно считать антипаттерн.

У использования этого шаблона есть и другие недостатки:[оригинальное исследование? ]

  1. Это загрязняет класс пространство имен с переменными только для чтения, которые могут быть бесполезны.
  2. В отличие от время компиляции тактическая полезность реализации постоянного интерфейса, случайное время выполнения артефакты не имеют большого практического значения (ср. маркерные интерфейсы которые также не имеют методов, но находятся полезно во время выполнения).
  3. Если совместимость двоичного кода требуется в будущих выпусках, постоянный интерфейс должен навсегда оставаться интерфейсом (его нельзя преобразовать в класс), даже если он не использовался в качестве интерфейса в обычном смысле.
  4. Без IDE, которая определяет, откуда берется константа, отслеживание ее до содержащего ее класса или интерфейса может занять много времени.
  5. Экземпляр интерфейса синтаксически не более полезен, чем само имя интерфейса (поскольку у него нет методов).
  6. Если разработчик не проверит какие-либо реализованные интерфейсы при добавлении константы в класс или сделает это, но не сделает опечатку в имени добавленной константы, значение константы может быть изменено незаметно. Рассмотрим пример 2 ниже.

Обратите внимание, что библиотеки Java сами используют постоянный шаблон интерфейса, показывая, что в некоторых ситуациях это может быть разумным выбором.[2]

Пример 1

общественный интерфейс Константы {	двойной ЧИСЛО ПИ = 3.14159;	двойной PLANCK_CONSTANT = 6.62606896e-34;}общественный учебный класс Расчеты орудия Константы {	общественный двойной getReducedPlanckConstant() {		возвращаться PLANCK_CONSTANT / (2 * ЧИСЛО ПИ);	}}

Пример 2

общественный интерфейс Константы {	общественный статический окончательный int	ПОСТОЯННЫЙ = 1;}общественный учебный класс Класс1 орудия Константы {	общественный статический окончательный int ПОСТОЯННЫЙ = 2;	// *	общественный статический пустота главный(Нить аргументы[]) бросает Исключение {		Система.из.println(ПОСТОЯННЫЙ);	}}

Перед добавлением строки, отмеченной звездочкой, запуск Class1 печатает 1. После добавления строки Class1 печатает 2. Обе версии компилируются без предупреждений или ошибок.

Альтернативы

Многие ловушки анти-шаблона можно избежать, преобразовав постоянный интерфейс в класс со статическими атрибутами:

общественный окончательный учебный класс Константы {	частный Константы() {		// ограничиваем создание экземпляров	}	общественный статический окончательный двойной ЧИСЛО ПИ = 3.14159;	общественный статический окончательный двойной PLANCK_CONSTANT = 6.62606896e-34;}

С Java 5, можно использовать статический импорт[3] чтобы иметь возможность использовать константы без квалификатора Constants:

импорт статических Константы.PLANCK_CONSTANT;импорт статических Константы.PI;общественный учебный класс Расчеты {	общественный двойной getReducedPlanckConstant() {		возвращаться PLANCK_CONSTANT / (2 * ЧИСЛО ПИ);	}}

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

В той или иной степени решены перечисленные выше проблемы:

  1. Поскольку статические члены могут быть импортированы специально, пространство имен класса не должно быть засорено всеми членами константного интерфейса.
  2. Семантика времени выполнения и времени компиляции более тесно согласована при использовании статического импорта вместо постоянных интерфейсов.
  3. Скомпилированный код имеет на одно ограничение двоичной совместимости меньше (это «класс Calculations реализует константы»).
  4. Поскольку статический импорт применяется только к текущему файлу (а не ко всей иерархии классов), легче определить, где объявлен каждый статический член.
  5. Меньше необходимости объявлять переменные постоянного типа интерфейса, и потенциально более ясно, что на самом деле не существует конкретного экземпляра.

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

Рекомендации

  1. ^ Блох, Джошуа, Эффективная Java, 2-е издание, стр. 98
  2. ^ "SwingConstants"
  3. ^ «Статический импорт»