簡體   English   中英

將使用者與不同的參數或不同的參數編號組合

[英]Combine Consumers with different arguments or different arguments number

假設我們的方法接收輸入 String並返回一些List 輸出 此輸出是一些生成器的結果,其中一些生成器取決於輸入,而有些則不取決於輸入-它們只是添加預定義的值。 我想將這些生成器實現為一些函數接口的列表(例如,Consumer),然后將它們組合為一個Consumer,然后將其應用於輸入String。

因此,我將能夠輕松,獨立地更換小型發電機。 但是問題是,並不是我所有的生成器都需要輸入 String作為參數,而我只是出於一個原因就將這個參數傳遞給了它-能夠將此類使用者與其他使用者組合在一起。

public class ConsumersTest {

private static <T, U> BiConsumer<T, U> combine(List<BiConsumer<T, U>> consumers) {
    return consumers.stream().reduce((arg1, arg2) -> {}, BiConsumer::andThen);
}

List<String> generate(String input) {
    ArrayList<String> output = new ArrayList<>();
    combine(getGenerators()).accept(input, output);
    return output;
}

private List<BiConsumer<String, List<String>>> getGenerators() {
    return Arrays.asList(
            this::addFirstDependent,
            this::addSecondIndependent
    );
}

private void addFirstDependent(String input, List<String> output) {
    if (input.contains("some string")) {
        output.add("First-Dependent");
    }
}

private void addSecondIndependent(String input, List<String> output) {
    output.add("Predefined Output");
}}

是否可以將不同的消費者合並到一個保護傘下並在一個地方應用? 還是這是一個壞主意,而不是正確的方法?

在模塊化軟件和適配器中具有通用接口以適合特定的實現並非不尋常的模式。 例如

public class ConsumersTest {

    List<String> generate(String input) {
        ArrayList<String> output = new ArrayList<>();
        generators.accept(input, output);
        return output;
    }

    private static <T, U> BiConsumer<T, U> ignoreFirstArg(Consumer<U> consumer) {
        return (t, u) -> consumer.accept(u);
    }

    private final BiConsumer<String, List<String>> generators =
        Stream.<BiConsumer<String, List<String>>>of(
                this::addFirstDependent,
                ignoreFirstArg(this::addSecondIndependent)
        ).reduce(BiConsumer::andThen).orElse((arg1, arg2) -> {});

    private void addFirstDependent(String input, List<String> output) {
        if (input.contains("some string")) {
            output.add("First-Dependent");
        }
    }

    private void addSecondIndependent(List<String> output) {
        output.add("Predefined Output");
    }
}

因此, ignoreFirstArg是不具有該第一個參數的方法的常規適配器。 可以有任意數量的適配器方法。 但是請注意,如果適配器是非常特定的,因此僅使用一次,那么也可以在組合代碼中編寫一個lambda表達式而不是方法引用。 請注意,我更改了代碼,以免每次調用generate(String input)都被重復評估,否則,當您不重用組合函數時,將它們組合就沒有意義,因為您也可以使用

List<String> generate(String input) {
    ArrayList<String> output = new ArrayList<>();
    Stream.<BiConsumer<String, List<String>>>of(
            this::addFirstDependent,
            ignoreFirstArg(this::addSecondIndependent)
    ).forEach(g -> g.accept(input, output));
    return output;
}

甚至更簡單

List<String> generate(String input) {
    ArrayList<String> output = new ArrayList<>();

    this.addFirstDependent(input, output);
    this.addSecondIndependent(output);

    return output;
}

維護起來並不比功能代碼差,因為每個生成器仍然由一行組成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM