我有一个类RequestParams
的层次结构,所有类都可以使用ExtArgs
创建。
public interface RequestParams {
}
我还创建了一个工厂RequestsFactory
,如下所示:
public class RequestFactory<P extends RequestParams> {
private final Logger logger = LoggerFactory.getLogger(RequestFactory.class);
final Class<P> paramsClass;
public RequestFactory(Class<P> paramsClass) {
this.paramsClass = paramsClass;
}
public Request<P> create(ExternalArgs args) {
P params = null;
try {
params = paramsClass.getDeclaredConstructor(ExternalArgs.getClass()).newInstance(args);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
logger.error("Failed to generate request", e);
}
return new Request<>("get", Collections.singletonList(params));
}
static <P extends RequestParams> RequestFactory<P> createFactory(
final Class<P> paramsClass) {
return new RequestFactory<P>(paramsClass);
}
}
我的客户端代码如下:
Request devInfoRequest = RequestFactory.createFactory(RequestType.SYSTEM_INFO.getRequestClass()).create(externalArgs);
我在订单地图请求类型中使用此ENUM:
public enum RequestType {
SYSTEM_INFO(DeviceInfoParams.class),
INTERFACES(InterfacesParams.class)
}
我的问题是 - 如何使用它,因为我不能将构造函数和静态构建器都添加到RequestParams接口(或抽象类)?
编辑:(AdamSkywalker's answer之后): 我希望我的客户端代码是:
Request<InterfacesParams> interfacesRequest =
RequestFactory.<InterfacesParams>createFactory(RequestType.INTERFACES.create(externalArgs)).create("get");
但它需要枚举返回函数来匹配泛型类型。
答案 0 :(得分:1)
也许它并不完全是您正在寻找的东西,但您的代码过于设计。为什么不:
public enum RequestType {
SYSTEM_INFO {
public RequestParams create(ExternalArgs args) { return new DeviceInfoParams(args); }
},
INTERFACES {
public RequestParams create(ExternalArgs args) { return new InterfacesParams(args); }
};
abstract RequestParams create(ExternalArgs args);
}
然后在没有反射技巧的情况下调用它:
Request req = new Request("get", singletonList(SYSTEM_INFO.create(args)));
你仍然可以使用你的工厂,但重点是消除反射的复杂性。
答案 1 :(得分:1)
正如您所观察到的,内置enum
功能的问题是每个枚举值必须具有相同的类型;它们不能有不同的类型参数(事实上,枚举类甚至不接受类型参数)。
一个选项是滚动你自己的枚举 - 只需用私有构造函数和每个实例的普通静态字段写一个class RequestType<P extends RequestParam>
。
但是如果RequestType
和RequestFactory<...>
类型真的只有你在这里显示的内容,那么通过写下来合并它们可能更有意义:
public final class RequestFactory<P extends RequestParams> {
public static final RequestFactory<DeviceInfoParams> SYSTEM_INFO =
new RequestFactory<>(DeviceInfoParams::new);
public static final RequestFactory<InterfacesParams> INTERFACES =
new RequestFactory<>(InterfacesParams::new);
private final Function<ExternalArgs, P> mRequestParamsCreator;
private RequestFactory(final Function<ExternalArgs, P> requestParamsCreator) {
mRequestParamsCreator = requestParamsCreator;
}
public Request<P> create(final ExternalArgs externalArgs) {
final P requestParams = mRequestParamsCreator.apply(externalArgs);
return new Request<P>("get", Collections.singletonList(requestParams));
}
}
(注意:上面使用了一些Java 8 / JDK 1.8功能以简洁。如果你仍然使用旧版本的Java,上面的方法仍然可以工作,但你必须写一些样板来填写差距。同样,如果DeviceInfoParams
和InterfacesParams
的相关构造函数声明任何已检查的异常,因为在这种情况下,它们不能隐式转换为java.util.function.Function
s。)
然后,您可以通过编写(例如):
来创建请求final Request<DeviceInfoParams> systemInfoRequest =
RequestFactory.SYSTEM_INFO.create(externalArgs);
final Request<InterfacesParams> interfacesRequest =
RequestFactory.INTERFACES.create(externalArgs);
与AdamSkywalker的方法一样,这完全避免了反射。