Определение значений полей как констант в Java - PullRequest
4 голосов
/ 21 июля 2011

Я реализую стандарт как объектно-ориентированную библиотеку в Java. Стандарт включает в себя множество сообщений, которые проходят через сеть через терминалы. Каждое сообщение реализовано как отдельный класс.

Некоторые поля представлены как типы символов, и эти поля имеют одно из значений, определенных в стандарте. Например,

public class OutgoingMessage {
    private char action;

и действие имеет эти значения,

'0' - Do not print
'1' - Print
'2' - Print and Forward
'3' - Print and Reply
'F' - Forward
'R' - Reply

Также некоторые классы имеют более 2 полей, подобных этому. В таких ситуациях их определение в качестве констант в классе может быть затруднено.

Так что я пытаюсь реализовать эти значения как

public class OutgoingMessage {
    private char action;

    public final class ActionTypes {
        public static final char DO_NOT_PRINT = '0';
        public static final char PRINT = '1';
        ...

И используя, как показано ниже

...
message.setAction(OutgoingMessage.ActionTypes.DO_NOT_PRINT);
...
message.setFooBar(OutgoingMessage.FooBarTypes.FOO_BAR);
...

Что вы думаете? Что-то не так с этим подходом? Как бы вы определили эти константы в библиотеке?

Большое спасибо

Ответы [ 5 ]

8 голосов
/ 21 июля 2011

Используйте перечисления в предпочтении int или char констант:

public enum Action {
    DoNotPrint,
    Print,
    PrintAndForward,
    PrintAndReply,
    Forward,
    Reply
}

public class OutgoingMessage {
     private Action action;

Если вам нужно связать char с действием, сделайте следующее:

public enum Action {
    DoNotPrint('0'),
    Print('1'),
    PrintAndForward('2'),
    PrintAndReply('3'),
    Forward('F'),
    Reply('R');

    private static Map<Character, Action> map = new HashMap<Character, Action>() {{
        for (Action action : Action.values()) {
            put(action.getChar(), action);
        }
    }};

    private final char c;

    private Action(char c) {
        this.c = c;
    }

    public char getChar() {
        return c;
    }

    public static Action parse(char c) {
        if (!MapHolder.map.containsKey(c))
            throw new IllegalArgumentException("Invalid char: " + c);
        return MapHolder.map.get(c);
    }
}

Вот как вы можете использовать метод разбора:

public static void main(String[] args) {
    System.out.println(Action.parse('2')); // "PrintAndForward"
    System.out.println(Action.parse('x')); // throws IllegalArgumentException
}
2 голосов
/ 21 июля 2011

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

public enum Action {
    DO_NOT_PRINT('0'),
    PRINT('1'),
    PRINT_AND_FORWARD('2'),
    PRINT_AND_REPLY('3'),
    FORWARD('F'),
    REPLY('R');

    private final char code;

    private Action(char code) {
        this.code = code;
    }

    public char getCode() {
        return code;
    }
}

Вы бы просто использовали константы enum в своей программе, и когдавам нужен код, вы звоните getCode на значение enum:

Action action = Action.DO_NOT_PRINT;
message.setAction(action);

// Suppose you need the char code:
char code = action.getCode();
1 голос
/ 21 июля 2011

Вы также можете немного глубже подумать об архитектуре и иметь класс Action (который также позволит избежать большого оператора switch в дальнейшем и отделить некоторый код от стандарта и сообщений).

Я бызатем избавьтесь от типов действий и сделайте их легко расширяемыми позже, просто добавив реализации Action.

interface Action {
  public void performAction(Standard standard, OutgoingMessage msg);
}

class PrintAction implements Action {
  // Implement the interface methods properly...  
}

class ForwardAction implements Action {
  // Implement the interface methods properly...  
}

Затем вы просто добавляете экземпляры действий к своему сообщению:

msg.addAction(new PrintAction());
msg.addAction(new ForwardAction());

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

1 голос
/ 21 июля 2011

Я считаю, что это хорошо. Но для простоты вы можете использовать Enum также, если вы используете как минимум JDK1.5

0 голосов
/ 21 июля 2011

То, что у вас есть, хорошо, но если вы просто хотите объявить константы, вы можете использовать интерфейс.

public class OutgoingMessage {
    private char action;

    public final interface ActionTypes {
        public static final char DO_NOT_PRINT = '0';
        public static final char PRINT = '1';
        ...

И, да, перечисления тоже хорошие.

...