2014-11-21 13 views
2

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

public static final String error_code1 = "Fatal Error"; 
public static final String error_code2 = "XXXX"; 
... 
... 

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

Но можете ли вы, ребята, дать мне несколько советов/аргументов с точки зрения программного обеспечения? (сцепление, сцепление, трудности технического обслуживания и т. д.)

+0

Это можно решить с помощью Enums. – Mirco

+0

Вы должны использовать enums в идеале в противном случае, используя интерфейс. –

ответ

3

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

public enum ErrorCode { 
    FATAL_ERROR("Fatal Error"), 
    X_ERROR("XXXX"); 

    public final String msg; 
    private ErrorCode(String msg) { 
     this.msg = msg; 
    } 
} 

Если это вас не устраивает по каким-то причинам, я бы с классом final полезности с частным (неиспользованного) конструктора.

Независимо от того, что поля являются статическими и окончательными, я бы не рассмотрел возможность иметь ссылку на A или реализовать A для получения констант.

+0

Не будет ли интерфейс лучше, чем последний класс с частным конструктором? –

+0

Эти поля представляют собой детали реализации, а не контракт класса. Просто потому, что это «удобно», это не значит, что это хорошая идея. Прежде чем вы это узнаете, кто-то * реализует * интерфейс для упрощения доступа к константам. Через 2 дня кто-то, кто не понимает, что поля статичны, начинает обходить объекты типа ErrorConstants. – aioobe

+0

Вы правы. В этом есть смысл. –

1

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

+0

Да, я думаю, что интерфейс не должен использоваться для констант, потому что он побеждает цель иметь интерфейс – hades

1

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

константа шаблон интерфейса является неэффективным использованием интерфейсов. То, что класс использует некоторые константы внутри, является деталью реализации. Внедрение постоянного интерфейса заставляет эту деталь реализации протекать в экспортированный API класса. Это не имеет никакого значения для пользователей класса, которые класс реализует постоянный интерфейс. На самом деле это может даже запутать их. Хуже того, он представляет собой обязательство: если в будущей версии класс модифицируется так, что ему больше не нужно использовать константы, он все равно должен реализовать интерфейс для обеспечения совместимости с двоичными файлами. Если нефинальный класс реализует константный интерфейс, все его подклассы будут иметь свои пространства имен, загрязненные константами в интерфейсе.

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

0

У констант String/int/... в другом классе есть одна проблема: они скопированы в константный пул использования класса use, и после этого никакого импорта в исходный класс не существует. Если вы затем измените значение константы, класс использования не будет перекомпилирован.

Решение будет заключаться в использовании интерфейса и «реализации» этого интерфейса; возможно, уродливый. Лучше использовать перечисление.

Для открытых областей законченного значения не будет использовать перечисление, но объектно-ориентированный подход:

abstract class ParseError extends RuntimeException 
class ExpressionExpectedError extends ParseError 
class DigitsMayNotFollowLeadingZeroError extends ParseError 
.. 

В Javadoc можно увидеть все дочерние классы ParseError. Здесь сами классы образуют значения домена, а экземпляр несет фактическую контекстную информацию. Это больше ООП. Вызов нескольких методов для объекта лучше, чем наличие нескольких переключателей на константах. Однако перечисление можно использовать и с категориальным методом: boolean errorHandledBySkippingToNextExpr().