Самое элегантное решение для цепочки асинхронных вызовов в Java? - PullRequest
5 голосов
/ 03 апреля 2012

В настоящее время я занимаюсь разработкой презентационного уровня приложения для 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 таких методов за один раз, и они должны запускаться по одному за раз.

Как я могу решить эту проблему гибко и элегантно?

Спасибо!

Ответы [ 2 ]

7 голосов
/ 03 апреля 2012

Позвольте мне убедиться, что я понимаю ... у вас есть серия интерфейсов if1, if2 .. ifn, и вы хотите, чтобы все они могли обрабатывать полученные данные.

СначалаИз всего, что было бы лучше, если бы if1, if2 и т. д. имели бы один и тот же интерфейс с двумя вашими основными методами: public void dataReceived(Data d) и public void onError(String reason).При этом вы можете просто передать List или Collection ваших получателей на 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, и если ссылка не будет нулевой, он вызовет next.dataReceived(d) в своем собственном dataReceived методе.Идея, аналогичная ServletFilter s, где каждый фильтр получает ServletRequest и затем вызывает chain.doFilter(request,response).

1 голос
/ 03 апреля 2012

Вы можете использовать библиотеку Google Guava, см. этот ответ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...