如何强制客户端实现具有相同类型的多个通用接口

时间:2018-12-10 15:11:53

标签: java oop design-patterns interface abstract-class

让我说我有一些通用接口

public interface Service<T> {
    T getData();
}

public interface ResponseBuilder<T> {
    void build(T response);
}

和一些使用这些接口的通用类

public class Orchestrator<T> {
    private Service<T> service;
    private List<ResponseBuilder<T>> responseBuilders;

    public Orchestrator(Service<T> serviceImpl, List<ResponseBuilder<T>> buildersImpl){
        this.service = serviceImpl;
        this.responseBuilders = buildersImpl; 
    }

    public void execute() {
        T response = service.getData();
        responseBuilders
            .stream()
            .map(builder -> builder.build(response))
            .forEach(data -> storageUtil.upload(data));
    }
}

当客户开发人员要使用这些API时,我如何强制他/她在这些通用接口的具体实现中传递相同的类型,以避免类型不匹配的异常。

在未指定Orchestrator类型的情况下创建的实例可以采用不同的类型作为参数 例如:-

public class App{
    public static void main(String[] args){
        ResponseBuilder<String> response1 = new SomeImpl(); // type STRING
        Service<Integer> service = new SomeServiceImpl(); // type INTEGER

        // completely valid and compilable code, will throw ex at runtime
        Orchestrator orch = new Orchestrator(service, Arrays.asList(response1));
   }
}

什么是更好的设计?

2 个答案:

答案 0 :(得分:0)

禁止使用原始类型。

    Orchestrator orch = new Orchestrator(service, Arrays.asList(response1));

那应该产生警告。不要发出警告。

    Orchestrator<T> orch = new Orchestrator<T>(service, Arrays.asList(response1));

答案 1 :(得分:0)

我认为您正在做的事是正确的,但是只缺少正确使用通用功能的部分。

您没有使用Orchestrator T的类型。

当您接受其他对象的通用类型实例时,可以验证它们是否具有相同的通用类型。

例如,在类Orchestrator中,您应该执行以下操作:

let poly_shapes = $('#clouds_1_')

此处的不匹配类型将在编译时引发错误。如果Orchestrator实例的类型定义为

,则此方法有效
public class Orchestrator<T> {

    private Service<? extends T> service;
    private List<? extends  ResponseBuilder<? extends  T>> responseBuilders;

    public Orchestrator(Service<? extends T> service, List<? extends  ResponseBuilder<? extends  T>> buildersImpl){
        this.service = service;
        this.responseBuilders = buildersImpl;
    }
}

此外,如果我们只有几种类型的通用可能性,那么最好的方法是使Orchestrator 抽象,并且扩展它的类应指定类型。例如,

= new Orchestrator<String>(....);

然后,使用一些具体的实现实例化Orchestrator,这在某种意义上不是通用的:

public class StringOrchestrator extends Orchestrator<String> {

    public StringOrchestrator(Service<? extends String> service,
                              List<? extends ResponseBuilder<? extends String>> buildersImpl) {
        super(service, buildersImpl);
    }
}