Spring-4 - 重构使用instanceof来调用适当的方法

时间:2016-10-19 12:19:16

标签: java spring-4

我有以下的接口和类集。 请注意doSomething方法。它必须在调用接口方法之前检查对象的实例。我想避免这种情况,因为它涉及在添加新车辆时更改此方法。在Spring工作的最佳方式是什么?

class SomeService {
  @Autowired
  VehicleRepairService<Car> carRepariService;

  @Autowired
  VehicleRepairService<Truck> truckRepairService;


  public void doSomething(String vehicleId) {
     Vehicle vehicle = getVehicle(vehicleId);
     if(vehicle instanceof Car) {
        carRepairService.repair(vehicle);
     } else {
        truckRepairService.repair(vehicle);
     }
  }
}

interface VehicleRepairService<T extends Vehicle> {
  void repair(T vehicle);
}

class CarRepairService implements VehicleRepairService<Car> {
    @Autowired
    SomeDependency some;

    void repair(Car vehicle) {
    .......
    }
}

class TruckRepairService implements VehicleRepairService<Car> {
  @Autowired
  DifferentDependency different;

   void repair(Truck vehicle) {
    .......
    }
}

2 个答案:

答案 0 :(得分:2)

由于没有一个答案有通用的解决方案。 Spring允许注入一个类型的所有实现。下面的解决方案没有经过测试我在文本编辑器中写了它。可以通过使VehicleRepairService成为抽象类来改进它,并使用例如ResolvableType检索此抽象类中的泛型类型。在每个实例中都不再需要实现getType方法。

class SomeService  {

    @Autowired
    private List<VehicleRepairService> vehicleRepairServices;


    public void doSomething(String vehicleId) {
        Vehicle vehicle = getVehicle(vehicleId);
        for(VehicleRepairService vehicleRepairService:vehicleRepairServices){
            if(vehicle.getClass().equals(vehicleRepairService.getType())){
                vehicleRepairService.repair(vehicle);
            }
        }
    }

    public Vehicle getVehicle(String id){
        return new Truck();
    }
}

interface VehicleRepairService<T extends Vehicle> {
    void repair(T vehicle);

    Class<T> getType();
}

class CarRepairService implements VehicleRepairService<Car> {

    public void repair(Car vehicle) {
    }

    @Override
    public Class<Car> getType() {
        return Car.class;
    }
}

class TruckRepairService implements VehicleRepairService<Truck> {

    public void repair(Truck vehicle) {
    }

    @Override
    public Class<Truck> getType() {
        return Truck.class;
    }
}

答案 1 :(得分:0)

一般情况下,如果instanceofswitchif .. else if ..一起interface Vehicle { public interface Visitor<T> { T visit(Car car); T visit(Truck truck); } <T> T accept(Visitor<T> visitor); } class Car implements Vehicle { @Override public <T> T accept(Visitor<T> visitor) { return visitor.visit(this); } }; class Truck implements Vehicle { @Override public <T> T accept(Visitor<T> visitor) { return visitor.visit(this); } }; ,您可以考虑使用Visitor pattern。对于你的代码,它意味着这样的事情:

Vehicle.Visitor<Void> repairVisitor = new Vehicle.Visitor<Void>()
{

    @Override
    public Void visit(Car car)
    {
        carRepairService.repair(car);
        return null;
    }

    @Override
    public Void visit(Truck truck)
    {
        truckRepairService.repair(truck);
        return null;
    }
};
vehicle.accept(repairVisitor);

然后,您可以在需要区分特定实例的位置创建新的访问者,无论是内联还是单独的类:

{{1}}

请注意,我将访客设为通用。然后你也可以让访客返回一些东西。