在这里,枚举一个switch语句合适吗?

orc*_*hid 6 java oop switch-statement

今天,我正在用Java创建一个Tetris克隆,当需要实现块生成机制时,我编写了这个带有枚举的switch语句。我被告知要尽可能避免使用switch语句,但是我不确定在这里是否可以避免使用switch语句,除非我彻底修改了我最初基于继承的设计选择。

为了实现不同类型的块,我决定制作一个名为Block的抽象超类,并为每种特定类型创建一个子类。我还做了一个枚举来标记块的类型。例如,一个ZBlock扩展Block对象将为它的Type字段变量分配Type.ZBlock枚举。

private void spawnBlock(Type type){
        switch(type){
            case I:
                currentBlock = new IBlock();
                break;
            case L:
                currentBlock = new LBlock();
                break;
            case J:
                currentBlock = new JBlock();
                break;
            case Z:
                currentBlock = new ZBlock();
                break;
            case S:
                currentBlock = new SBlock();
                break;
            case T:
                currentBlock = new TBlock();
                break;
            default:
                currentBlock = new OBlock();
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我开始考虑不使用switch语句的方法时,除了摆脱所有子类并在单个非抽象Block类中对不同块的行为进行编程之外,我别无选择。但是,由于不同的块具有不同的形状和壁球数据,可能会变得一团糟。那么在这里switch语句是一个不错的选择吗?如果没有,如何改善我的代码,为什么?

Gho*_*ica 3

\n

我被告知要尽可能避免使用 switch 语句

\n
\n\n

这是正确的,但你在这里所做的可能没问题。

\n\n

要点是:您不希望到处都有这样的 switch 语句。它们很糟糕,因为它们将事物耦合在一起。当您一遍又一遍地重复“相同”的开关模式时,这可能会变成维护噩梦。因为枚举类型的更改......意味着您必须查看每个开关以确定是否需要进行调整。

\n\n

因此,当您能够在大部分代码中隐藏这种切换时(最好只在少数几个地方,最好是在一个地方这样做),那就没问题了。

\n\n

尽管如此,更好的方法可能是将整个 switch 语句替换为以下一行:

\n\n
currentBlock = type.createBlock();\n
Run Code Online (Sandbox Code Playgroud)\n\n

换句话说:为什么不将知识直接放入枚举类本身呢?当然,这还有其他含义,例如可能违反单一责任原则

\n\n

自然的是,表示不同类型块的枚举也提供了创建此类块的方法(考虑到类型确定您需要哪种类型的块子类的唯一信息)。

\n\n

请注意:您不必将开关移到枚举中。您可以完全避免在这里切换:

\n\n
enum Type {\n  I(IBlock::new), L(LBlock::new), ...;\n\n  private Supplier<? extends Block> supplier;\n  private Type(Supplier<? extends Block> supplier) {\n    this.supplier = supplier;\n  }\n\n  public Block getBlock() {\n    return supplier.get();\n \xc2\xa0}\n
Run Code Online (Sandbox Code Playgroud)\n\n

(我没有通过编译器运行上面的内容,所以要小心拼写错误)

\n