问题描述
我有以下代码,我需要重构它以降低复杂性并增加模块化和封装性。我还需要降低 ck 指标值。
private void initialiseVehicle(String vehicleName) {
if(vehicleName.equals("Boat")) {
vehicle = new Boat("Apollo ");
}
else if(vehicleName.equals("Ship")) {
vehicle = new Ship("Cruizz");
}
else if(vehicleName.equals("Truck")) {
vehicle = new Truck("Ford F-650");
}
else if(vehicleName.equals("Motorcycle")) {
vehicle = new Motorcycle("Suzuki");
}
else if(vehicleName.equals("Bus")) {
vehicle = new Bus("Aero");
}
else if(vehicleName.equals("Car")) {
vehicle = new Car("BMW");
}
else if(vehicleName.equals("Bicycle")) {
vehicle = new Bicycle("A-bike");
}
else if(vehicleName.equals("Helicopter")) {
vehicle = new Helicopter("Eurocopter");
}
else if(vehicleName.equals("Airplane")) {
vehicle = new Airplane("BA");
}
else if(vehicleName.equals("Tram")) {
vehicle = new Tram("EdinburghTram");
}
else if(vehicleName.equals("Train")) {
vehicle = new Train("Virgin",4);
}
}
你如何重构这段代码?切换案例会降低任何复杂性吗?
解决方法
一个选项可能如下所示:
Map<String,Function<String,Vehicle>> constructors = new HashMap<>();
constructors.put("Boat",name -> new Boat(name));
constructors.put("Ship",name -> new Ship(name));
然后 if/else 代码可能看起来像
Function<String,Vehicle> constructor = constructors.get(vehicleName);
Vehicle vehicle = constructor.apply("Apollo");
,
使用反射:
Vehicle vehicle;
Map<String,String> m = new HashMap<>() {{
put("Boat","Apollo");
put("Ship","Cruizz");
// etc
}};
private void initializeVehicle(String name) throws Exception {
vehicle = (Vehicle) Class.forName(name)
.getConstructor(String.class)
.newInstance(m.get(name));
}
但是老实说,我认为您的原始代码足够简单。圈复杂度本身不应成为目标。
这段代码在 CK 中的得分可能很低,但不如 if/else 链容易理解。
所以,考虑一下你打算用它做什么,上面的例子对于事先不知道要创建的类的库非常有用。
这是完整的运行示例
import java.util.*;
import java.lang.reflect.*;
import static java.lang.System.out;
class Vehicle {
String name;
public Vehicle(String aName) {
name = aName;
}
}
class Boat extends Vehicle {
public Boat(String s) {
super(s);
}
}
class Ship extends Vehicle {
public Ship(String s) {
super(s);
}
}
class Main {
Vehicle vehicle;
Map<String,String> m = new HashMap<>() {{
put("Boat","Apollo");
put("Ship","Cruizz");
// etc
}};
private void initializeVehicle(String name) throws Exception {
vehicle = (Vehicle) Class.forName(name).getConstructor(String.class).newInstance(m.get(name));
}
public static void main(String... args) throws Exception {
Main main = new Main();
main.initializeVehicle("Ship");
System.out.println(main.vehicle.name); // prints Cruizz as expected
}
}