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语句是一个不错的选择吗?如果没有,如何改善我的代码,为什么?
\n\n\n我被告知要尽可能避免使用 switch 语句
\n
这是正确的,但你在这里所做的可能没问题。
\n\n要点是:您不希望到处都有这样的 switch 语句。它们很糟糕,因为它们将事物耦合在一起。当您一遍又一遍地重复“相同”的开关模式时,这可能会变成维护噩梦。因为枚举类型的更改......意味着您必须查看每个开关以确定是否需要进行调整。
\n\n因此,当您能够在大部分代码中隐藏这种切换时(最好只在少数几个地方,最好是在一个地方这样做),那就没问题了。
\n\n尽管如此,更好的方法可能是将整个 switch 语句替换为以下一行:
\n\ncurrentBlock = type.createBlock();\n
Run Code Online (Sandbox Code Playgroud)\n\n换句话说:为什么不将知识直接放入枚举类本身呢?当然,这还有其他含义,例如可能违反单一责任原则。
\n\n但很自然的是,表示不同类型块的枚举也提供了创建此类块的方法(考虑到类型是确定您需要哪种类型的块子类的唯一信息)。
\n\n请注意:您不必将开关移到枚举中。您可以完全避免在这里切换:
\n\nenum 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