【问题标题】:Most elegant solution to chain asynchronous calls in java?在java中链接异步调用的最优雅的解决方案?
【发布时间】:2012-04-16 20:26:01
【问题描述】:

我目前正在开发一个 android 应用程序的表示层。

我使用的 api 看起来像这样:

public interface errorInterface{
    public void onError(String reason);
}

public interface if1 extends errorInterface{
    public void dataReceived1(Data data);
}
public interface if2 extends errorInterface{
    public void dataReceived2(Data data);
}   

public void fetchData1(if1 receiver) {}
public void fetchData2(if2 receiver) {}

也就是说;要获取数据,您需要提供一个接收器,该接收器将在未来某个时间接收操作结果。

当您一次只需要调用一个方法时,这非常有效,但现在我已经到了需要一次调用 10+ 个这样的方法,并且它们需要一次执行一个的地步。

如何以灵活优雅的方式解决这个问题?

谢谢!

【问题讨论】:

    标签: java design-patterns asynchronous


    【解决方案1】:

    让我确保我理解..您有一系列接口if1if2..ifn,并且您希望它们都能够处理接收到的数据。

    首先,如果if1if2 等与您的两个基本方法的接口相同:public void dataReceived(Data d)public void onError(String reason),那将是最好的。这样,您只需将接收器的ListCollection 传递给fetchData,它就可以遍历集合并在每个集合上调用dataReceived(d)

    如果出于某种原因,这不可行,我会尝试使用适配器将它们引导到fetchData 的类似接口中。例如:

    public interface DataReceiver extends ErrorInterface {
      public void dataReceived(Data d); 
      //or just scrap the ErrorInterface all together and make these into 1 interface
    }
    
    public class AbstractIFAdapter<T extends ErrorInterface> implements DataReceiver {
      private T target;
      public AbstractIFAdapter(T target) { this.target = target);
      public void onError(String reason) { target.onError(reason); }
      protected T getTarget() { return target; }
    }
    
    public class IF1Adapter extends AbstractIFAdapter<IF1> {
      public IF1Adapter(IF1 target) { super(target); }
      public dataReceived(Data d) { getTarget().dataReceived1(d); }
    }
    
    public class IF2Adapter extends AbstractIFAdapter<IF2> {
      public IF2Adapter(IF2 target) { super(target); }
      public dataReceived(Data d) { getTarget().dataReceived2(d); }
    }
    

    现在有了这些,我们可以做这样的事情:

    List<DataReceiver> dataReceivers = new ArrayList<DataReceiver>();
    dataReceivers.add(new IF1Adapter(someIf1Implementation));
    dataReceivers.add(new IF2Adapter(someIf2Implementation));
    fetchData(dataReceivers);
    
    public void fetchData(Collection<DataReceiver> receivers) {
    
      try {
        Data d = getSomeData();
        for (DataReceiver dr : receivers) {
          dr.dataReceived(d);
        }
      }
      catch (Exception e) {
        for (DataReceiver dr : receivers) {
          dr.onError(e.getMessage());
        } 
      }
    }
    

    根据您的确切需求,还有其他可能适用的模式,例如访问者或责任链类型模式,您可以在链表类型构造中将接收者链接在一起,每个接收者以递归方式调用下一个构造 - 这会很好,因为fetchData 不需要知道它正在获取一个集合,它只是获取对链中 top 适配器的引用。因此,AbstractIFAdapter 将引用另一个 AbstractIFAdapter,我们称它为 next,如果引用不为空,它将在自己的 dataReceived 方法中调用 next.dataReceived(d)。与ServletFilters 类似的想法,每个过滤器获取ServletRequest,然后调用chain.doFilter(request,response)

    【讨论】:

    • 非常有帮助的答案。我最终根据我的需要修改了您的第一个建议版本!
    猜你喜欢
    • 2011-03-31
    • 2010-10-04
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 2011-02-13
    • 1970-01-01
    相关资源
    最近更新 更多