2015-03-13 105 views
2

我很快就會顯示我想在「最清晰」的方式來實現的:實現響應式定位枚舉的最簡單方法是什麼? 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 

我去下一個方法是通過一個指南針類將所有方向鏈接成一個圓圈..像鏈接電路清單一樣工作... < - > NORTH < - > EAST < - > SOUTH < - > WEST < - > NORTH < - > ...因此,Compass可以有一個靜態函數,可以調用該鏈接列表中的任何成員向左或向右步進,導致正確的方向改變。但是代碼並沒有按照我想要的方式運行。

所以我的問題到底是不是有人有這樣的代碼的經驗,或者有一個想法如何以一個很好的消除方式實現所需的結果?

+0

我不確定我是否理解。你問我們如何在Orientation枚舉中實現turn()方法嗎? – 2015-03-13 19:39:29

+0

我正在問如何以一種很好和非冗餘的方式實現這樣的方法的想法(你可以寫一個開關的情況下,但這將是不好的冗餘方面,因爲例如WEST.turn(左)將總是導致相同的方向,即南) – Jan 2015-03-13 19:43:59

+0

@Jan你真的需要一個枚舉'轉'嗎?我的意思是,它只能是'LEFT'或'RIGHT'/ – 2015-03-13 19:46:03

回答

4

我發現Map解決方案沒有錯。如果你想要更多的東西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

是的,不幸的是我讀了Josh Bloch,告訴我不要使用序號索引,這與您告訴我的原因完全相同。 考慮到你認爲地圖解決方案很好,正如你在上面我的評論中看到的,我有更多的方向和可能性,導致靜態映射(40行)的代碼塊更大。這仍然是一個很好的解決方案嗎? – Jan 2015-03-13 19:54:38

+1

@Jan:如果邏輯更復雜,我會說Map解決方案更好。也許你可以通過在Orientation和Turn中添加一個數字代碼(比如表示度數)來簡化其構建邏輯(避免if/else太多)。 – leonbloy 2015-03-13 20:00:13

+0

我真的沒有考慮使用模數類來獲得正確的索引和管理溢出..謝謝! – Jan 2015-03-13 20:11:24

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

這其實是一個不錯的方法:) – 2015-03-13 20:16:49

+0

這會導致數組索引超出範圍! java中的一個數組並沒有把-1的索引作爲數組的末尾,就像在C中一樣。這個答案應該被修正。 – Jan 2015-03-16 20:40:31

+0

@Jan什麼時候會發生這種異常? – 2015-03-16 20:41:58

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()這樣的東西。給你非常簡潔的語法。

相關問題