如何重构以降低此代码的复杂性?

问题描述

我有以下代码,我需要重构它以降低复杂性并增加模块化和封装性。我还需要降低 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 
      
    }
}