java 中泛型的工厂模式

Factory pattern with generics in java

我在针对特定用例使用泛型实现工厂时遇到问题

我有模型 classes:

class BaseModel { }

class ModelA extends BaseModel { }

class ModelB extends BaseModel { }

以及相应的服务:

class Service<T extends BaseModel> { }

class ServiceA extends Service<ModelA> {}

class ServiceB extends Service<ModelB> {}

我的工厂class,根据它服务的模型创建服务:

class Factory {
    private Map<Class<? extends BaseModel>, Class<? extends Service>> registry;

    Factory(){
        registry = new HashMap<>();
        registry.put(ModelA.class, ServiceA.class);
        registry.put(ModelB.class, ServiceB.class);
    }

    Service getService(Class<? extends BaseModel> clazz) throws IllegalAccessException, InstantiationException {
        return registry.get(clazz).newInstance();
    }
}

还有一个使用工厂的class

class Handler<T extends BaseModel>{
    private Service<T> myService;

    Handler(Class<T> modelClass) {
        Factory fact = new Factory();
        try {
            myService = fact.getService(modelClass);
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
    }
}

我收到一条关于使用工厂获取服务的行的警告:

"Unchecked assignment 'Service' to 'Service<T>'"

我明白为什么我会收到消息,因为 getService 方法 returns Service,但我需要 Service<T> 并且对如何将代码更改为得到 Service<T>

有什么建议吗?

谢谢!

Java 泛型和继承有时会反直觉地相互作用,即 Service<ModelA>Service<BaseModel> 无关(在继承方面)。但是,您可以编写 getService() 的两个实现并显式调用服务构造函数(不通过反射)。您的处理程序将需要您的模型的一个实例,这样 Java 重写将 select 为您提供正确的服务构造函数。

我在最初的回答中没有想到的是:您需要捕获工厂中的所有 BaseModel 实现(重写将选择最具体的方法)并且您的服务必须针对要拉取的接口实现串在一起。

class BaseModel { }

class ModelA extends BaseModel { }

class ModelB extends BaseModel { }

interface Service { }

class ServiceImplementation<T extends BaseModel> implements Service { }

class ServiceFactory {
    public static Service getService(ModelA model) { return new ServiceImplementation<ModelA>(); }
    public static Service getService(ModelB model) { return new ServiceImplementation<ModelB>(); }
    public static Service getService(BaseModel model) { 
        throw new UnsupportedOperationException("Unknown Service Model");
    }
}

class Handler<T extends BaseModel> {
    private Service service;

    Handler(T model) {
        service = ServiceFactory.getService(model);
    }
}

在这里,您可以捕获 class 作为 T 和 return 它的一个实例(带强制转换):

<T extends BaseModel> Service<T> getService(Class<T> clazz) throws IllegalAccessException, InstantiationException {
    return (Service<T>) registry.get(clazz).newInstance();
}