2015-03-13 5 views
2

Я быстро показать то, что я хочу достичь в «ясном» способом:Самый простой способ получить отзывчивую ориентацию enum? Java

public enum Orientation { 
    NORTH, WEST, SOUTH, EAST } 

public enum Turn { 
    LEFT, RIGHT } 

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

Orientation orient = Orientation.NORTH; 
// orient points to NORTH now 
orient = orient.turn(Turn.LEFT); 
// orient points to WEST now 

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

EnumMap<Orientation, EnumMap<Turn, Orientation>> 

и карты всех направлений статический, но -й на огромный кусок map.get.put.get .... и, вероятно, немного слишком передозировка, Altough в результате этого желаемого эффекта:

directionMap.get(NORTH).get(LEFT) 
// the value would then be WEST 

Следующий способ я пошел был через класс Compass, что связывает все ориентации в круг .. Работает как LinkedCircuitList ... < -> NORTH < -> EAST < -> SOUTH < -> WEST < -> NORTH < -> ... Итак, Compass может иметь статическую функцию, которая вызывает любой член этого связанного списка и шаг влево или вправо, что приведет к правильному изменению направления. Но код действительно не работал так, как я этого хотел.

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

+0

Я не уверен, что понимаю. Вы спрашиваете нас, как реализовать метод turn() в перечислении Orientation? –

+0

Я прошу идеи о том, как реализовать такой метод в хорошем и не избыточном виде (вы могли бы написать случай переключения, но это было бы плохо с точки зрения избыточности, например, WEST.turn (LEFT) всегда приводило бы к в том же направлении, а именно SOUTH) – Jan

+0

@Jan Вам действительно нужно перечисление для 'Turn'?Я имею в виду, что это может быть только «LEFT» или «RIGHT»/ –

ответ

4

Я не вижу ничего плохого в решении карты. Если вы хотите что-то более consise:

public enum Orientation { 
    NORTH, EAST, SOUTH, WEST; 

    private static Orientation[] vals = values(); 

    Orientation turnTo(Turn t) { 
     return vals[(4 + this.ordinal() + (t == Turn.RIGHT ? 1 : -1)) % 4]; 
    } 
} 

Это, однако, является менее чистым и ремонтопригодны (это нарушило бы, если кто-то изменяет порядок перечислений).

Немного чище (но менее consise):

public enum Orientation { 
    NORTH(0), EAST(1), SOUTH(2), WEST(3); 

    private final int p; 

    Orientation(int p) { 
     this.p = p; 
    } 

    private static Orientation[] vals = new Orientation[4]; 
    static { 
     for(Orientation o : Orientation.values()) 
      vals[o.p] = o; 
    } 

    Orientation turnTo(Turn t) { 
     return vals[(4 + this.p + (t == Turn.RIGHT ? 1 : -1)) % 4]; 
    } 
} 
+0

Да, к сожалению, я прочитал, что Джош Блох сказал мне не использовать порядковое индексирование именно той же причины, о которой вы мне говорите. Относительно того, что вы считаете решение карты приятным, как вы можете видеть в моем комментарии выше, у меня есть еще несколько направлений и возможность поворота, что приводит к еще большему кодовому блоку для статического отображения (40 строк). Это все еще считается хорошим решением? – Jan

+1

@Jan: Я бы сказал, что решение карты еще лучше, если логика сложнее. Возможно, вы можете упростить свою логику построения (избегать слишком много if/else), добавляя числовой код как к Ориентации, так и к повороту (скажем, чтобы представлять степени). – leonbloy

+0

Я действительно не думал об использовании классов modulo для получения правильных индексов и управления переполнением .. спасибо! – Jan

1

Я думаю, что ваша идея циклического списка очень хорошо:

public enum Turn { 
    LEFT(-1), RIGHT(1); 

    private final int offset; 

    private Turn(int offset) { 
     this.offset = offset; 
    } 

    public int offset() { 
     return this.offset; 
    } 
} 

public enum Orientation { 
    NORTH, EAST, SOUTH, WEST; 

    private static final List<Orientation> orientations = 
     Arrays.asList(NORTH, EAST, SOUTH, WEST); // to not depend on ordinal 

    public Orientation turn(Turn to) { 
     int size = orientations.size(); 
     int myIndex = orientations.indexOf(this); 
     int remainder = (myIndex + to.offset()) % size; 
     int index = remainder < 0 ? size + remainder : remainder; 
     return orientations.get(index); 
    } 
} 

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

+1

Это на самом деле хороший подход :) –

+0

Это приводит к исключению индекса Array из-за пределов! Массив в java не передает индекс -1 как конец массива, как в C. Этот ответ должен быть исправлен. – Jan

+0

@Jan Когда возникает это исключение? –

1

Не использовать порядковые, и легко понять:

public enum Orientation { NORTH, WEST, EAST, SOUTH; 

    static { 
     NORTH.left = WEST; 
     NORTH.right = EAST; 
     WEST.left = SOUTH; 
     WEST.right = NORTH; 
     EAST.left = NORTH; 
     EAST.right = SOUTH; 
     SOUTH.left = EAST; 
     SOUTH.right = WEST; 
    } 

    private Orientation left; 
    private Orientation right; 

    public Orientation turnTo(Turn t) { return t == Turn.LEFT ? left : right; } 
} 
1

Другой способ обмануть Java в принятии этого является использование методов вместо полей:

enum Orientation { 

    NORTH { 
     Orientation left(){return WEST;} 
     Orientation right(){return EAST;} 
    }, 
    EAST { 
     Orientation left(){return NORTH;} 
     Orientation right(){return SOUTH;} 
    }, 
    SOUTH { 
     Orientation left(){return EAST;} 
     Orientation right(){return WEST;} 
    }, 
    WEST { 
     Orientation left(){return SOUTH;} 
     Orientation right(){return NORTH;} 
    }; 

    abstract Orientation left(); 
    abstract Orientation right(); 

    public Orientation turn(Turn where){ 
     return where == Turn.LEFT ? this.left() : this.right(); 
    } 
} 

Вы можете спасти себя turn() и просто напишите что-нибудь вроде Orientation.North.left(), если хотите. Дает вам очень сжатый синтаксис.

 Смежные вопросы

  • Нет связанных вопросов^_^