java - 具有静态工厂方法或构造函数的工厂模式

标签 java design-patterns constructor factory

我有一个类层次结构 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)构造函数和一个普通的静态字段。

但是如果RequestTypeRequestFactory<...>类型实际上只有您在此处显示的内容,那么通过编写以下内容来合并它们可能更有意义:

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,上述方法仍然有效,但您必须编写一些样板文件填补空白。同样,如果 DeviceInfoParamsInterfacesParams 的相关构造函数声明任何已检查异常,因为在这种情况下它们不能隐式转换为 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/

相关文章:

c# - 构造函数中 GetDbContext 时出现 System.ArgumentNullException

java - 找到递归调用的最后一个实例

java - 不想在子类中使用构造函数

java - 在 View 中保留 Controller 的引用或使用监听器

OOP 是否所有属性都有 getter 和 setter

java - 什么应该是最好的设计方法

java - 在 Xtext 编辑器中实现不区分大小写

java - 如何在没有正则表达式的情况下解析字符串

javascript - 在构造函数中使用 'this' 关键字是否会增加总体内存使用量?

Java - 在默认构造函数之前执行的方法