首页 > 解决方案 > 如何编写一个覆盖方法来返回 Java 中调用类的实例

问题描述

我对 Java 和设计模式比较陌生。我正在尝试为我的应用程序实现 Builder 模式。我有interface一个方法,buildbuild方法将类作为参数并返回相同的值。

public interface TestInterface {
    public TestInterface withTest(int start);
    public <T> T build();
}

到目前为止,我已经interface在一个类中实现了这个并覆盖了GenerateBuilder类中的方法,它工作正常

public class GenerateNumbers {

private String start;

private GenerateGSRN(GenerateBuilder builder) {
        this.start = builder.start;
    }

    public static class GenerateBuilder implements TestInterface {

        private String start;

        @Override
        public TestInterface withGcp(String start) {
            this.start = start;
            return this;
        }

        @Override
        public GenerateNumbers build() {
            return new GenerateNumbers(this);
        }

    }
}

但是我想将GenerateBuilder覆盖方法的类移到它自己的单独类中,以便它可以被任何其他类使用(使其变得通用,这样我就不必再次编写此代码)。

但是正如我们所看到的,该GenerateBuilder Build函数与它紧密耦合,GenerateNumbers因此我无法移动它。我想在其中和期间更改Build方法,以便它将类的实例返回给调用类。Interfaceoverriding

例如:如果GenerateNumbers正在调用构建方法,那么build方法应该返回GenerateNumbers。如果GenerateNumbersRandom正在调用,则build方法应返回GenerateNumbersRandom.

我尝试了几件事但没有奏效:

在界面中: public <T> T build(Class clazz);

在覆盖中:

@Override
        public <T> T build(Class clazz) {
            return clazz.newInstance();
        }

我希望我能够正确解释这个问题。有人可以建议我如何完成这项工作。

标签: javabuilderbuilder-pattern

解决方案


据我了解,您可以:

  • 声明你的接口有泛型类型 ( Builder)
  • 声明你想要由实现接口的类构建的类型 ( NumberGenerator)
  • 将构建器声明为接口的实现,对于泛型类型,它将构建的类 ( NumberGeneratorBuilder implements Builder<NumberGenerator>)
  • Builder接口中,访问实际类型的泛型,在运行时实例化这个类型的新实例。

例如,这将给出如下内容:

import java.lang.reflect.ParameterizedType;

public interface Builder<T> {

  default T build() throws IllegalAccessException, InstantiationException {
    // in a more production-ready application, you would not reference item with their index but lookup through correct criterion to avoid getting a bad class instantiated
    return ((Class<T>) ((ParameterizedType) this.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0]).newInstance();
  }
}
public class NumberGenerator {

  public static NumberGenerator instance() throws InstantiationException, IllegalAccessException {
    return new NumberGeneratorBuilder().build();
  }

  // Note that visibility is important here, default constructor needs to be visible from the Builder class, and not from its implementation
  NumberGenerator() {

  }

  public static class NumberGeneratorBuilder implements Builder<NumberGenerator> {

  }

}


推荐阅读