Spring-4 - 重构使用 instanceof 调用适当的方法
Spring-4 - Refactoring use of instanceof for calling appropriate method
我有以下一组接口和 类。
注意 doSomething
方法。它必须在调用对象的接口方法之前检查对象的实例。我想避免这种情况,因为它涉及在添加新 Vehicle 时更改此方法。在 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) {
.......
}
}
一般来说,如果您同时拥有 instanceof
和 switch
或 if .. 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);
}
};
然后您可以在需要区分特定实例的地方创建一个新的访问者,内联或单独 class:
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);
请注意,我将访问者设为通用。然后您还可以让访问者返回一些东西。
因为 none 个答案具有通用解决方案。 Spring 允许注入一个类型的所有实现。下面的解决方案未经测试我是在文本编辑器中编写的。可以通过使 VehicleRepairService 成为抽象 class 并使用例如 ResolvableType 检索此抽象 class 中的通用类型来改进它。不再需要在每个实例中实现 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;
}
}
我有以下一组接口和 类。
注意 doSomething
方法。它必须在调用对象的接口方法之前检查对象的实例。我想避免这种情况,因为它涉及在添加新 Vehicle 时更改此方法。在 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) {
.......
}
}
一般来说,如果您同时拥有 instanceof
和 switch
或 if .. 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);
}
};
然后您可以在需要区分特定实例的地方创建一个新的访问者,内联或单独 class:
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);
请注意,我将访问者设为通用。然后您还可以让访问者返回一些东西。
因为 none 个答案具有通用解决方案。 Spring 允许注入一个类型的所有实现。下面的解决方案未经测试我是在文本编辑器中编写的。可以通过使 VehicleRepairService 成为抽象 class 并使用例如 ResolvableType 检索此抽象 class 中的通用类型来改进它。不再需要在每个实例中实现 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;
}
}