我有一个类层次结构 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);
我在订单 map 请求类型中使用此 ENUM:
public enum RequestType {
SYSTEM_INFO(DeviceInfoParams.class),
INTERFACES(InterfacesParams.class)
}
我的问题是 - 如何使用它,因为我无法将构造函数或静态构建器添加到 RequestParams 接口(interface)(或抽象类)?
编辑:(在 AdamSkywalker's answer 之后): 我希望我的客户端代码是:
Request<InterfacesParams> interfacesRequest =
RequestFactory.<InterfacesParams>createFactory(RequestType.INTERFACES.create(externalArgs)).create("get");
但它需要枚举返回函数来匹配泛型类型。
最佳答案
正如您所观察到的,内置 enum
的问题特点是每个枚举值必须具有相同的类型;它们不能有不同的类型参数(事实上,枚举类甚至不接受类型参数)。
一种选择是滚动您自己的枚举 - 只需编写 class RequestType<P extends RequestParam>
每个实例都有一个私有(private)构造函数和一个普通的静态字段。
但是如果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
。)
然后您可以通过编写(例如)来创建请求:
final Request<DeviceInfoParams> systemInfoRequest =
RequestFactory.SYSTEM_INFO.create(externalArgs);
final Request<InterfacesParams> interfacesRequest =
RequestFactory.INTERFACES.create(externalArgs);
与 AdamSkywalker 的方法一样,这完全避免了反射。
关于java - 具有静态工厂方法或构造函数的工厂模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35895298/