如何简化这段 Java 代码?
How to simplify this Java code?
我正在为名为 Spigot (spigotmc.org) 的 Minecraft 服务器软件编写一些 Java 代码,我刚刚编写了这个。目标是检查变量 block
的每一侧并检查墙上的标志,如您所见。它应该只需要找到一个。然后它会更新它等等。我知道这段代码可以简化,但目前我看不出如果不为条件语句中的代码创建一个全新的函数,我不想这样做。有没有更好的方法来写这个条件?
// Get an attached sign
Block sign;
if ((sign = block.getRelative(BlockFace.NORTH)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
} else if ((sign = block.getRelative(BlockFace.EAST)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
} else if ((sign = block.getRelative(BlockFace.WEST)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
} else if ((sign = block.getRelative(BlockFace.SOUTH)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
}
您的内部 if 范围始终相同,因此您可以在条件之间使用 "or" 命令:
// Get an attached sign
Block sign;
if (((sign = block.getRelative(BlockFace.NORTH)).getType() == Material.WALL_SIGN)
|| ((sign = block.getRelative(BlockFace.EAST)).getType() == Material.WALL_SIGN)
|| ((sign = block.getRelative(BlockFace.WEST)).getType() == Material.WALL_SIGN)
|| ((sign = block.getRelative(BlockFace.SOUTH)).getType() == Material.WALL_SIGN)
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
}
可能是循环?
// Get an attached sign
Block sign;
BlockFace[] faces = new BlockFace[] {
BlockFace.NORTH,
BlockFace.EAST,
BlockFace.WEST,
BlockFace.SOUTH};
for(BlockFace face : faces) {
if ((sign = block.getRelative(face)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
break;
}
}
当您有很多选择要查看时,这种方法很有效。另外,如果你在其他地方做类似的逻辑,一定要创建一个所有有相同需求的客户都可以调用的函数!
根据DRY原则,您需要重复使用重复的部分。在您的示例中,整个 if 块是相同的,除了面部。
将 ifs 替换为 for:
List<BlockFace> blockFaces = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.WEST, BlockFace.SOUTH);
for (BlockFace face : blockFaces) {
Sign sign = block.getRelative(face);
if (sign.getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
break;
}
}
提取方法:
private boolean updateAttachedSign(Block block, BlockFace face) {
Sign sign = block.getRelative(face);
if (sign.getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
return true;
}
return false;
}
{
boolean signIsUpdated =
updateAttachedSign(block, BlockFace.NORTH) ||
updateAttachedSign(block, BlockFace.EAST) ||
updateAttachedSign(block, BlockFace.WEST) ||
updateAttachedSign(block, BlockFace.SOUTH);
}
第二种解决方案,尽管总体上是更好的方法,但对于您的情况来说似乎有点过于复杂。我会坚持第一个。
@Constantin编辑:
谨慎使用短路条件。请参考这篇优秀的 post 了解其中的意义 https://softwareengineering.stackexchange.com/questions/284415/short-circuit-evaluation-is-it-bad-practice
我正在为名为 Spigot (spigotmc.org) 的 Minecraft 服务器软件编写一些 Java 代码,我刚刚编写了这个。目标是检查变量 block
的每一侧并检查墙上的标志,如您所见。它应该只需要找到一个。然后它会更新它等等。我知道这段代码可以简化,但目前我看不出如果不为条件语句中的代码创建一个全新的函数,我不想这样做。有没有更好的方法来写这个条件?
// Get an attached sign
Block sign;
if ((sign = block.getRelative(BlockFace.NORTH)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
} else if ((sign = block.getRelative(BlockFace.EAST)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
} else if ((sign = block.getRelative(BlockFace.WEST)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
} else if ((sign = block.getRelative(BlockFace.SOUTH)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
}
您的内部 if 范围始终相同,因此您可以在条件之间使用 "or" 命令:
// Get an attached sign
Block sign;
if (((sign = block.getRelative(BlockFace.NORTH)).getType() == Material.WALL_SIGN)
|| ((sign = block.getRelative(BlockFace.EAST)).getType() == Material.WALL_SIGN)
|| ((sign = block.getRelative(BlockFace.WEST)).getType() == Material.WALL_SIGN)
|| ((sign = block.getRelative(BlockFace.SOUTH)).getType() == Material.WALL_SIGN)
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
}
可能是循环?
// Get an attached sign
Block sign;
BlockFace[] faces = new BlockFace[] {
BlockFace.NORTH,
BlockFace.EAST,
BlockFace.WEST,
BlockFace.SOUTH};
for(BlockFace face : faces) {
if ((sign = block.getRelative(face)).getType() == Material.WALL_SIGN) {
org.bukkit.block.Sign data = (Sign) sign.getState();
data.setLine(1, "OFF");
data.update();
break;
}
}
当您有很多选择要查看时,这种方法很有效。另外,如果你在其他地方做类似的逻辑,一定要创建一个所有有相同需求的客户都可以调用的函数!
根据DRY原则,您需要重复使用重复的部分。在您的示例中,整个 if 块是相同的,除了面部。
将 ifs 替换为 for:
List<BlockFace> blockFaces = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.WEST, BlockFace.SOUTH); for (BlockFace face : blockFaces) { Sign sign = block.getRelative(face); if (sign.getType() == Material.WALL_SIGN) { org.bukkit.block.Sign data = (Sign) sign.getState(); data.setLine(1, "OFF"); data.update(); break; } }
提取方法:
private boolean updateAttachedSign(Block block, BlockFace face) { Sign sign = block.getRelative(face); if (sign.getType() == Material.WALL_SIGN) { org.bukkit.block.Sign data = (Sign) sign.getState(); data.setLine(1, "OFF"); data.update(); return true; } return false; } { boolean signIsUpdated = updateAttachedSign(block, BlockFace.NORTH) || updateAttachedSign(block, BlockFace.EAST) || updateAttachedSign(block, BlockFace.WEST) || updateAttachedSign(block, BlockFace.SOUTH); }
第二种解决方案,尽管总体上是更好的方法,但对于您的情况来说似乎有点过于复杂。我会坚持第一个。
@Constantin编辑:
谨慎使用短路条件。请参考这篇优秀的 post 了解其中的意义 https://softwareengineering.stackexchange.com/questions/284415/short-circuit-evaluation-is-it-bad-practice