2015-03-13 103 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()这样的东西。给你非常简洁的语法。

相关问题