简体   繁体   English

Java - 如何将未知的接口实现传递给泛型方法

[英]Java - How to pass unknown implementation of interface to generic method

I have such issue (of course its just an example).我有这样的问题(当然这只是一个例子)。 I have processor where I have to repair a car.我有处理器,我必须在那里修理汽车。 I have a string as a json of car object.我有一个字符串作为汽车对象的 json。 I dont know implementation of ServiceStation and I have only class of car implementation.我不知道 ServiceStation 的实现,我只有汽车实现类。 I have to parse json to car object and provide it to service station.我必须将 json 解析为汽车对象并将其提供给服务站。 There is any proper solution to achieve this ?有什么合适的解决方案来实现这一目标吗?

public interface Car {}

public class BMW implements Car {}

public interface ServiceStation<T extends Car> {
    public void repair(T car)
}

public class BMWServiceStation<BMW> {
    public void repair(BMW car) { ... }
}

public class ServiceStationProcessor {

    public void process(String carJson, Settings settings) {
        Class<? extends Car> carClass = settings.getCarClass();
        ServiceStation serviceStation = settings.getServiceStation();

        JavaType javaType = objectMapper.getTypeFactory().constructType(carClass);

        Object<? extends Car> obj = objectMapper.readValue(carJson, javaType); <-- ?? something like this?
        serviceStation.repair(obj)
    }

}

You could have a 'type' field in your json that identifies a concrete Car sub-type (eg 'bmw' or 'mazda').您可以在 json 中有一个“type”字段,用于标识具体的 Car 子类型(例如“bmw”或“mazda”)。 Then you could use annotations on the Car interface to tell Jackson what to instantiate based on the 'type' value.然后,您可以在 Car 界面上使用注释来告诉 Jackson 根据“类型”值实例化什么。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = BMW.class, name = "bmw"),
  @JsonSubTypes.Type(value = Mazda.class, name = "mazda")
})
@JsonIgnoreProperties(ignoreUnknown = true)
public interface Car {

}

Then it's type-safe and logic in processor simplifies:然后它是类型安全的,并且处理器中的逻辑简化了:

public class ServiceStationProcessor {

  public void process(String carJson, Settings settings) {
      ServiceStation serviceStation = settings.getServiceStation();
      Car obj = objectMapper.readValue(carJson, Car.class);
      serviceStation.repair(obj);
  }

}

You can reach your result with a combination of:您可以通过以下组合来达到您的结果:

  • Jackson deserialization of children classes杰克逊儿童类的反序列化
  • A visitor pattern for your service station您的服务站的访客模式

Service Station服务站

This is the "visitor" part of the implementation.这是实现的“访问者”部分。

You should have one single implementation exposing N methods for the N different concrete types (instead of having N different implementations of the same single-method interface).你应该有一个单一的实现,为N不同的具体类型公开N方法(而不是有N不同的同一个单一方法接口的实现)。

Something like this:像这样的东西:

public interface ServiceStation {

    void repair(Bmw bmw);

    void repair(Mercedes mercedes);

}

//Single implementation with a dedicated method per type of car
public class ServiceStationImpl implements ServiceStation {

    @Override
    public void repair(Bmw bmw) {
        System.out.println("Repair bmw");
    }

    @Override
    public void repair(Mercedes mercedes) {
        System.out.println("Repair mercedes");
    }
}

Car abstract class and its implementations Car抽象类及其实现

This will be the "visited" part of your implementation.这将是您实现的“访问”部分。

You defined Car as being an interface .您将Car定义为interface

Jackson allows deserialization of sub types but using abstract class rather than interface . Jackson 允许反序列化子类型,但使用abstract class而不是interface

Also, I take chance to add an abstract method which accepts a ServiceStation .此外,我有机会添加一个接受ServiceStation的抽象方法。 That will allow each concrete car implementation to let the ServiceStation (the visitor) "visit" themselves (the visited):这将允许每个具体的汽车实现让 ServiceStation(访问者)“访问”自己(被访问者):

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes(
    {
        @JsonSubTypes.Type(value = Bmw.class, name = "Bmw"),
        @JsonSubTypes.Type(value = Mercedes.class, name = "Mercedes")
    }
)
public abstract class Car {
    public abstract void accept(ServiceStation serviceStation);
}

public final class Bmw extends Car {
    @JsonIgnore
    private final String type = "Bmw";

    @Override
    public void accept(ServiceStation serviceStation) {
        serviceStation.repair(this); //<-- will call the Bmw method of the service station
    }
}

public final class Mercedes extends Car {
    @JsonIgnore
    private final String type = "Mercedes";

    @Override
    public void accept(ServiceStation serviceStation) {
        serviceStation.repair(this); //<-- will call the Mercedes method of the service station
    }
}

Main code主要代码

At this point, it becomes as simple as this:此时,它变得如此简单:

public class ServiceStationProcessor {

    public void process(String carJson, Settings settings) throws JsonProcessingException {
        Class<? extends Car> clazz = settings.getCarClass(); //<-- get the car class as you already do
        ServiceStation serviceStation = settings.getServiceStation(); //<-- get the service station
        objectMapper.readValue(carJson, clazz).accept(serviceStation); //<-- deserialize the json into the concrete car class (Jackson will pick the right type of car), then ask the car to accept the service station (the car will dispatch to the correct type)
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法将实现传递给声明通用接口(Java)的方法 - Can't pass implementation to method declaring generic interface (Java) 如何在Java方法中将接口的实现作为变量传递? - How to pass an implementation of an interface as a variable in a method in Java? 如何获取Java中通用接口实现的方法对象 - How to obtain method object for generic interface implementation in Java Java 使用泛型参数和默认方法实现编译功能接口失败 - Java failed to compile Functional Interface with generic parameter and default method implementation 通用接口方法和实现类 - generic interface method and implementation classes Java-如何将对象传递给KeyListener接口的实现? - Java - how to pass objects to implementation of KeyListener interface? 如何在Java中使用泛型来创建一个泛型接口,该接口定义仅接受实现作为参数的方法? - How would I use generics in Java to create a generic interface that defines a method that only accepts the implementation as a parameter? 具有未知通用接口类型的Java通用编程 - Java generic programming with unknown generic type of interface Java-如何使用泛型定义接口方法 - Java - How to define interface method with generic 如果我已经有一个泛型的实现,如何声明一个接口方法 - How to declare an interface method if i already have an implementation with generic
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM