Comment mettre en œuvre une promesse en java qui change le type de sortie

éclat :

Je suis en train de mettre en place un système simple promesse en java. Je le fais pour usage spécial afin s'il vous plaît ne recommande pas de bibliothèques.

J'ai un problème lorsque je tente de mettre en œuvre une thenApply()méthode qui prend une fonction en tant que paramètre, semblable à ce que CompletableFuture a et renvoie donc une promesse avec un autre type.

L'interface de promesse:

public interface Promise<T> {
    Promise<T> then(Consumer<T> handler);

    <U> Promise<U> thenApply(Function<T, U> handler);
}

Ma mise en œuvre à ce jour:

public class PromiseImpl<T> implements Promise<T> {

    private List<Consumer<T>> resultHandlers = new ArrayList<>();

    public PromiseImpl(CompletableFuture<T> future) {
        future.thenAccept(this::doWork);
    }

    @Override
    public Promise<T> then(Consumer<T> handler) {
        resultHandlers.add(handler);
        return this;
    }

    @Override
    public <U> Promise<U> thenApply(Function<T, U> handler) {
        // How to implement here??? I don't have the result yet
        handler.apply(?);
    }

    private void onResult(T result) {
        for (Consumer<T> handler : resultHandlers) {
            handler.accept(result);
        }
    }

    private Object doWork(T result) {
        onResult(result);
        return null;
    }
}

Le problème est que je ne sais pas le résultat de mon avenir initial dans la thenApply()méthode, donc je ne peux pas appeler mon gestionnaire. Je ne veux pas aussi appeler future.get()parce que cette méthode bloque.

Comment pourrais-je faire ce travail?

ernest_k:

Le vrai problème est dans la conception de votre Promisegenre. Il tient un ensemble de callbacks, tous doivent être invoquées à la fin. Ceci est un problème fondamental (limitation de fonctionnalité générique autour du type de retour de thenApplyla fonction). Cela peut être résolu en changeant votre Promisemise en œuvre de retourner une newpromesse à chaque fois qu'un gestionnaire est enregistré, au lieu de retourner this, de sorte que chaque objet promesse aura son propre gestionnaire d'invoquer.

En plus de résoudre cela, il est une meilleure conception pour la programmation de style fonctionnel, que vous pouvez faire vos Promiseobjets immuables.

Je change l'interface être:

interface Promise<T> {
    <U> Promise<U> thenApply(Function<T, U> handler);
    Promise<Void> thenAccept(Consumer<T> consumer);
}

Le « Enchaînement » de callbacks peut alors se faire autour des objets futurs auxquels chaînés Promiseinstances ont des références. Ainsi , la mise en œuvre peut ressembler à :

class PromiseImpl<T> implements Promise<T> {

    private CompletableFuture<T> future;

    public PromiseImpl(CompletableFuture<T> future) {
        this.future = future;
    }

    @Override
    public <U> Promise<U> thenApply(Function<T, U> function) {
        return new PromiseImpl<>(this.future.thenApply(function));
    }

    @Override
    public Promise<Void> thenAccept(Consumer<T> consumer) {
        return new PromiseImpl<>(this.future.thenAccept(consumer));
    }

    private void onResult(T result) {
        this.future.complete(result);
    }

    private Object doWork(T result) {
        onResult(result);
        return null;
    }
}

Et à l'aide qui peut être aussi simple que:

Promise<String> stringPromise = new PromiseImpl<>(new CompletableFuture<String>());
Promise<Long> longPromise = stringPromise.thenApply(str -> Long.valueOf(str.length()));
Promise<Void> voidPromise = stringPromise.thenAccept(str -> System.out.println(str));

EDIT:
En ce qui concerne le commentaire de Michael sur la récupération de la valeur: qui n'a pas été ajouté comme il n'a pas été dans l'original PromiseAPI. Mais il est assez facile d'ajouter:

T get(); //To the interface

Et mis en œuvre avec:

public T get() {
    //try-catch 
    return this.future.get();
}

Note: cela commence à ressembler de plus en plus comme une duplication de CompletableFuture, ce qui pose la question de savoir pourquoi faire du tout. Mais en supposant qu'il y aura d' autres Promiseméthodes -comme dans cette interface, la méthode serait envelopper l'API future.


Si vous avez besoin d'utiliser le même Promiseobjet avec une liste de dossiers d'appel, alors vous avez pas d'autre choix que de paramétrer l' Promiseinterface avec les deux Functionparamètres de type béton:

public interface Promise<T, U>

Et Une serait pas en mesure d'être une méthode paramètre générique sur thenou thenApply.

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=203668&siteId=1
conseillé
Classement