0

Я новичок в функциональном программировании (и Java), и я хочу создать что-то приятное с его помощью, но не могу понять, как это сделать.Повторить один раз с помощью функционального интерфейса

Я использую BiConsumer (java.util.function.BiConsumer) для вызовов на сервер.

Я пытаюсь написать код, который отправляет некоторый запрос серверу с существующими данными (вызов Public createSomeTask()), только если он не работает, соединитель выполнит повторную попытку только один раз.

Код isync, Private createSomeTask() вызывает updateTaskStage().

Проблема заключается в том, что у меня много вызовов в коннекторе (много createSomeTask()) с текущей реализацией, код не выглядит хорошо, и я уверен, что есть способ сделать это лучше, используя функциональные интерфейсы или расширяя BiConsumer или любой другой хороший способ в Java 8 lile, отражение, метод invoke и т. Д.

См. Код ниже. Надеюсь, кто-то может мне помочь.

//Main 
public class Main { 
    public static void main(String[] args) throws InterruptedException { 
     Connector connector = new Connector(); 
     connector.createSomeTask("started",(response, error)->{ 
     }); 
    } 
} 

//Connector Class 
import java.util.function.BiConsumer; 

public class Connector { 
    static String taskStage = null; 

    public void createSomeTask(final String taskName, 
           final BiConsumer<ServerResponse, ServerError> consumer) { 
     createSomeTask(taskName, true, consumer); 
    } 

    private void createSomeTask(final String taskName, 
           boolean retry, 
           final BiConsumer<ServerResponse, ServerError> consumer) { 
     updateTaskStage((newStage, error)->{ 
      if(error!=null) { 
       if (retry) { 
        createSomeTask(taskName, false, consumer); //The 'recursive' retry call 
        return; 
       } else { 
        consumer.accept(null, error);//only after second failure 
        return; 
       } 
      } 
      consumer.accept(new ServerResponse(),null); 
     }); 

    } 

    //re-uses existing task or starting a new one when the current is null/failed 
    private void updateTaskStage(final BiConsumer<String, ServerError> consumer) { 
     if(taskStage ==null || taskStage != "failed") 
      consumer.accept(taskStage,null); 
     else 
     { 
      taskStage = "started"; 
      consumer.accept(taskStage,null); 
     } 
    } 

    class ServerResponse{} 
    class ServerError{} 
} 
+0

Ваш код уже использует BiConsumer (функциональный интерфейс), лямбда-выражения, так что еще вы хотели бы сделать. Если вы ищете какое-то асинхронное решение, я бы предложил изучить CompletableFuture –

+0

Да, но проблема здесь заключается в уродливом рекурсивном вызове с параметром «повторить», установленным в true или false. Я ищу способ, возможно, расширить BiConsumer, чтобы добавить, возможно, первого потребителя в качестве поля, которое будет автоматически вызываться – Igal

ответ

0

Там нет причин, чтобы проверить retry флаг потребителя, как вы можете составить функцию делать правильные вещи, прежде чем передать его updateTaskStage:

private void createSomeTask(
    String taskName, boolean retry, BiConsumer<ServerResponse, ServerError> consumer) { 

    BiConsumer<String, ServerError> direct 
     = (s, e) -> consumer.accept(e==null? new ServerResponse(): null, e); 

    BiConsumer<String, ServerError> actual = retry? 
     (string, error) -> { 
      if(error!=null) updateTaskStage(direct); else direct.accept(string, null); 
     }: 
     direct; 

    updateTaskStage(actual); 
} 

Во-первых, функция создается прохождение перевод ответного ответа на предоставленного потребителя.

Тогда, если retry is true, функция состоит из другой функции, которая сделает вторую попытку в случае ошибки. Для второй попытки прямая функция может быть передана в updateTaskStage, устраняя необходимость в рекурсии.

Как представляется, что параметр retry не должен был быть одним из вариантов, но только часть вашей попытки решить проблему, теперь вы можете избавиться от него, когда всегда выполняет одну повторную попытку предназначена:

public void createSomeTask(
    String taskName, BiConsumer<ServerResponse, ServerError> consumer) { 

    BiConsumer<String, ServerError> direct 
     = (s, e) -> consumer.accept(e==null? new ServerResponse(): null, e); 

    BiConsumer<String, ServerError> actual= 
     (string, error) -> { 
      if(error!=null) updateTaskStage(direct); else direct.accept(string, null); 
     }; 

    updateTaskStage(actual); 
}