你怎么能避免重复?

时间:2015-12-28 01:01:15

标签: java

我正在使用Java,并试图在不同的情况下为不同的事情提供不同的任务,但有时它们会做同样的事情。这会导致一些重复(实际上是长行,而不是简短的方法名称),但是有一种简单的方法可以避免这些重复吗?

if(direction == Direction.UP) {
    doThingA(); // same thing as down
    doCustomThing1();
    doSameThing(); // all do this
    doCustomThing5();
} else if(direction == Direction.DOWN) {
    doThingA();
    doCustomThing2();
    doSameThing();
    doCustomThing6();
} else if(direction == Direction.RIGHT) {
    doThingB() // same thing as left
    doCustomThing3();
    doSameThing();
    doCustomThing7();
} else if(direction == Direction.LEFT) {
    doThingB()
    doCustomThing4();
    doSameThing();
    doCustomThing8();
}

下面是实际代码,正如您所看到的,自定义内容只是略有不同,但我不知道如何简化:

if(direction == Direction.UP) {
    box.setAsBox(size.value/2, Constants.WORLD_HEIGHT/2);
    bodyDef.position.set(new Vector2(rand.nextFloat()*(Constants.WORLD_WIDTH-size.value)+size.value/2, -Constants.WORLD_HEIGHT*0.5f));
    body = gameWorld.world.createBody(bodyDef);
    body.setLinearVelocity(new Vector2(0f, 5f));
} else if(direction == Direction.DOWN) {
    box.setAsBox(size.value/2, Constants.WORLD_HEIGHT/2);
    bodyDef.position.set(new Vector2(rand.nextFloat()*(Constants.WORLD_WIDTH-size.value)+size.value/2, Constants.WORLD_HEIGHT*1.5f));
    body = gameWorld.world.createBody(bodyDef);
    body.setLinearVelocity(new Vector2(0f, -5f));
} else if(direction == Direction.RIGHT) {
    box.setAsBox(Constants.WORLD_WIDTH/2, size.value/2);
    bodyDef.position.set(new Vector2(-Constants.WORLD_WIDTH*0.5f, rand.nextFloat()*(Constants.WORLD_HEIGHT-size.value)+size.value/2));
    body = gameWorld.world.createBody(bodyDef);
    body.setLinearVelocity(new Vector2(5f, 0f));
} else if(direction == Direction.LEFT) {
    box.setAsBox(Constants.WORLD_WIDTH/2, size.value/2);
    bodyDef.position.set(new Vector2(Constants.WORLD_WIDTH*1.5f, rand.nextFloat()*(Constants.WORLD_HEIGHT-size.value)+size.value/2));
    body = gameWorld.world.createBody(bodyDef);
    body.setLinearVelocity(new Vector2(-5f, 0f));
}

2 个答案:

答案 0 :(得分:4)

当我看到一个枚举作为switch语句或if-else梯形图中的条件时,并且编写控制语句的人拥有枚举,我认为这是代码味道。

考虑这个替代方案,而不是打开枚举,为什么不使用你在其他地方做的同样的事情?我建议你把多态性放在这里。

首先,如果没有对枚举有意义的默认实现,请使用一些抽象方法定义方向枚举。这与下面示例中的getWidth()相同。

其次,添加您可能想要的具有合理默认值的任何非抽象方法。然后,您可以像在普通Java多态中一样覆盖这些方法。这与下面示例中的getHeight()相同。

这种方法有很多优点。

  1. 如果你想添加更多方向(让我们说你从4个方向转到8个方向,增加向上,向上,向右,向下),那你就没有了遍历整个代码库并添加其他if-else语句。您只需在枚举中为这些新路线添加特定于实施的代码,即可完成。一切正常。
  2. 添加默认行为非常简单,您无需在代码库中的多个位置保持同步。
  3. 您的调用代码中的代码行数会减少您拥有的枚举数量。如果您有10个枚举,并且必须为每个枚举编写10个调用,那么您将拥有121行代码(占调用和控制语句),但在您开始使用多态之后,您将拥有10个代码行(没有控制语句,只是方法调用)。这应该会减少你的圈复杂度。
  4. 你明确地将枚举的功能封装在枚举本身中。你必须要小心一点,如果你坚持这种方法,Enums最终可能会知道系统的太多部分,但一般来说,我发现这不是问题。
  5. 方向枚举

    public enum Direction {
        UP {
            public int getWidth() {
                return 50;
            }
            @Override
            public int getHeight() {
                return 100;
            }
        },
        DOWN {
            public int getWidth() {
                return 30;
            }
        };
    
        public abstract int getWidth();
        public int getHeight() {
            return 10;
        }
    }
    

    现在您的调用代码看起来像这样。

    box.setAsBox(direction.getWidth(), direction.getSize());
    bodyDef.position.set(direction.getPositionVector());
    body = gameWorld.world.createBody(direction.getBody());
    body.setLinearVelocity(direction.getLinearVelocity());
    

答案 1 :(得分:1)

您可以重构所有值,并根据条件进行设置。因此,您只需使用值调用方法。遵循这个逻辑:

if (direction == Direction.UP) {
    boxWidth = size.value / 2;
    boxHeight = Constants.WORLD_HEIGHT / 2;
    ...
} else if 
...

在所有代码之后,您只需使用变量中设置的值调用方法。

...
box.setAsBox(boxWidth, boxHeight);
...