有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring4重构使用instanceof调用适当的方法

我有以下一组接口和类。 注意doSomething方法。在调用对象上的接口方法之前,它必须检查对象的实例。我希望避免这种情况,因为这涉及到在添加新车时更改此方法。春天做这件事最好的方法是什么

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) 个答案

  1. # 1 楼答案

    因为没有一个答案有一个通用的解决方案。Spring允许注入类型的所有实现。下面的解决方案没有经过测试,我是在文本编辑器中编写的。它可以通过使VehiclePairService成为一个抽象类并使用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;
        }
    }
    
  2. # 2 楼答案

    一般来说,如果您有instanceofswitchif .. else if ..,您可以考虑使用Visitor pattern。对于您的代码,它的含义如下:

    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);
        }
    };
    

    然后,您可以在需要区分特定实例的地方创建一个新的访问者,可以是内联的,也可以是单独的类:

    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);
    

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