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();
}
我在针对特定用例使用泛型实现工厂时遇到问题
我有模型 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();
}