3

我有几个扩展父类的子类,被迫有一个统一的构造函数。我有一个队列,其中包含这些类的列表,它必须扩展 MergeHeuristic。我目前拥有的代码如下所示:

    Class<? extends MergeHeuristic> heuristicRequest = _heuristicQueue.pop();
    MergeHeuristic heuristic = null;    

    if(heuristicRequest == AdjacentMACs.class)
        heuristic = new AdjacentMACs(_parent);
    if(heuristicRequest == SimilarInterfaceNames.class)
        heuristic = new SimilarInterfaceNames(_parent);
    if(heuristicRequest == SameMAC.class)
        heuristic = new SameMAC(_parent);

有什么方法可以简化动态实例化类,类似于:

heuristic = new heuristicRequest.somethingSpecial();

这将使 if 语句块变平。

4

4 回答 4

3

看起来您正在使用队列上的类作为一种标志来指示要实例化的请求类型。另一种不使用反射的方法是通过引入一个枚举来指示请求类型,使用工厂方法使这个标志行为显式:

public enum HeuristicType {

  AdjacentMACsHeuristic(AdjacentMACs.class) {
    @Override public MergeHeuristic newHeuristic(ParentClass parent) {
      return new AdjacentMACs(parent);
    }
  },
  SimilarInterfaceNamesHeuristic(SimilarInterfaceNames.class) {
    @Override public MergeHeuristic newHeuristic(ParentClass parent) {
      return new SimilarInterfaceNames(parent);
    }
  },
  ... // other types here.
  ;

  private final Class<? extends MergeHeuristic> heuristicClass;
  public Class<? extends MergeHeuristic> getHeuristicClass() {
    return heuristicClass;
  }

  abstract public MergeHeuristic newHeuristic(ParentClass parent);

  private HeuristicType(Class<? extends MergeHeuristic> klass) {
    this.heuristicClass = klass;
  }

}

然后您的客户端代码变为:

Queue<HeuristicType> _heuristicQueue = ...
HeuristicType heuristicRequest = _heuristicQueue.pop();
MergeHeuristic heuristic = heuristicRequest.newHeuristic(_parent);

与反射相比,使用枚举的主要优点是:

  • 您明确说明了添加新启发式类型的要求,即必须有一个启发式类并且您必须能够基于父级实例化它。
  • 您在系统中有一个点,您可以在其中查看所有可用的启发式类型。
  • 通过将实例化抽象为工厂方法,您可以使用替代构造函数签名。
于 2012-11-20T16:36:15.023 回答
2

您可以使用反射,但它不会使代码更漂亮。

try {
    Constructor<? extends MergeHeuristic> heuristicConstructor = 
            heuristicRequest.getConstructor(_parent.getClass());
    heuristic = heuristicConstructor.newInstance(_parent);
} catch (Exception ex) {
    // TODO Handle this
}

仅当您计划开设很多不同的课程时才这样做。如果它只有 3 个,请不要打扰,您的代码就可以了。

于 2012-11-20T16:16:18.347 回答
1

不幸的是,您不能强制一个类具有特定的构造函数或静态方法——两者在您的情况下都非常有用。

由于所有构造函数都采用相同的参数,因此还有另一种使用动态类实例化来简化代码的方法:

Constructor c = heuristicRequest.getConstructor(ParentClass.class).
heuristic = c.newInstance(_parent);

请注意,您的代码不包含 _parent 的类类型 - 在我命名的代码示例中ParentClass.class- 您必须使其适应您的代码。

于 2012-11-20T16:13:30.450 回答
0

Class.forName(heuristicRequest.getName())一种选择吗?

然后constructor heuristicRequestClass.getDeclaredConstructor(_parent.getClass());

最后的heuristic = constructor.newInstance(_parent);

于 2012-11-20T16:16:44.100 回答