从void-visitor返回数据而无需更改抽象访问者

时间:2019-06-20 12:55:56

标签: java oop factory visitor abstract-factory

我正在使用Java框架,该框架提供了某种用于处理元素的访客模式。有一个提供方法AbstractProcessor<T>的抽象超类public abstract void process(T visitedElement)(我不能更改)。

然后,我定义了此类处理器的几个具体实现,并通过Factory Pattern实例化它们,然后通过它们的公共超类型使用它们。现在,如何从那里获取任何类型的信息?我显然不能简单地返回一些东西,因为抽象的处理方法是void类型。

到目前为止,我唯一的想法就是可以添加到具体实现中的数据字段(因为我无法更改抽象超类),因此可以执行以下操作:

public class MyProcessor extends AbstractProcessor<SomeType> {
public String data;

  @Override
  public void process(SomeType t) {
  [do stuff...]
  this.data = "some important info";
  }
}

但是要从-假设它们不构成数据字段的常见超级类型的列表中接收数据-我将不得不做一些难看的类型检查和强制转换,如下所示:

List<AbstractProcessor> list = getProcessors();
list.forEach(p -> {
  someType.processWith(p); //someType accepts AbstractProcessor's and then runs their process-method
  if(p instanceOf MyProcessor) 
    System.out.println( ((MyProcessor)p).data );
  }
});

还有其他方法可以检索在process方法期间计算出的某种类型的数据吗?

3 个答案:

答案 0 :(得分:0)

我不会在这里使用字段。相反,请定义一个合适的接口,例如具有 T getResult()方法的 ResultProcessor 。然后让所有需要产生结果的子类实现该接口。

当然,您仍然必须强制转换,但至少可以使用通用T来灵活使用,并且客户可以调用方法而不是直接进行字段访问。

答案 1 :(得分:0)

我认为您在这里有一个本质上无法解决的问题。我了解您在说:

  • 您已经编写了几个AbstractProcessor子类。
  • 他们都做不同的事情,并产生不同的结果。
  • 您希望将它们全部同等对待,作为AbstractProcessor的实例。

但是,如果它们都产生不同的结果,则不能将它们全部视为同一类AbstractProcessor的实例。您必须知道所用的处理器类型才能解释结果。

您有两个选择。第一种选择是统一结果。例如,您可能有一个名为ResultHandler的接口,如下所示:

interface ResultHandler {
   void handleSumResult(int result);
   void handleConcatResult(String result);
   void handleSomeOtherProcessorResult(Whatever result);
}

传入ResultHandler的实例(在构造过程中或在单独的handleResult方法中),然后(在每个处理器内)调用适合该处理器类型的ResultHandler方法。如果您有几个不同的处理器以某种方式生成和,则至少它们都可以调用相同的handleSumResult API,而您不必在任何地方进行instanceof

另一种策略是放弃对所有处理器进行同等处理的尝试。我认为这可能是更好的选择。您的代码显然知道它需要使用哪种处理器,因此只需继续实例化该处理器,使用它,然后从您定义的任何API中收集结果即可。如果出于某种原因必须对处理器进行同等对待(例如,用户指定了处理器类,可能是在配置文件中指定了该类),请将该抽象上移一个级别,然后让用户指定一个拥有整个处理器类的类。处理数据并收集结果的过程。用法不是指定MyProcessor,,而是指定MySomethingElse,然后MySomethingElse实例化MyProcessor并处理结果。

答案 2 :(得分:0)

例如,您可以使处理器将数据“推送”到哈希映射,该哈希映射可以传入或全局访问。

public class MyProcessor extends AbstractProcessor<SomeType> {
  public Map<Object, String> data;

  @Override
  public void process(SomeType t) {
  [do stuff...]
  this.data.put(this, "some important info");
  }
}

这样,客户端可以获得哪个抽象处理器添加了哪些信息的信息,它所需要的就是访问地图。