类似于intstream的java静态构建

ttisahbt  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(337)

我的目标是提供一个类来构建一个函数链,以便在之后执行一些任务。这是我目前能想到的
函数类

public class Loop {
    private final int from;
    private final int to;

    private Loop(int from, int to) {
        this.from = from;
        this.to = to;
    }

    public static Loop from(int from) {
        return new Loop(from, 0);
    }

    public static Loop to(int to) {
        return new Loop(0, to);
    }

    public void execute(Executable executable) {
        for (int i = from; i < to; i++) {
            executable.execute();
        }
    }
}

可执行接口

@FunctionalInterface
public interface Executable {
    void execute();
}

它可以用于一个参数(from或to),如

Loop.to(10).execute(() -> {});

但我希望它能适用于多种参数,比如

Loop.from(5).to(10).execute(() -> {});

我怎样才能做到这一点?另外,我不确定static from和static to方法是否适合使用一个冗余参数的循环类。

093gszye

093gszye1#

有几种方法可以采取。解决方案越复杂,通常就越复杂。让我们从一个简单的解决方案开始。

public class Loop {
    private final int from;
    private final int to;

    private Loop(Builder builder) {
        this.from = builder.from();
        this.to = builder.to();
    }

    public static Builder from(int from) {
        return new Builder().from(from);
    }

    public static Builder to(int to) {
        return new Builder().to(to);
    }

    public void execute(Runnable executable) {
        for (int i = from; i < to; i++) {
            executable.run();
        }
    }

    public static class Builder {
        private int from = 0;
        private Integer to = null;

        private Builder() {}

        public Builder from(int from) {
            this.from = from;
            return this;
        }

        private int from() {
            return from;
        }

        public Builder to(int to) {
            this.to = to;
            return this;
        }

        private int to() {
            return to;
        }

        public void execute(Runnable runnable) {
            Objects.requireNonNull(runnable);
            new Loop(this).execute(runnable);
        }
    }
}

ideone演示
这已经很了不起了。但我们可以打电话 from(...) 或者 to(...) 多次。如果我们只允许一个电话 from(...) 在此之后,只允许呼叫 to(...) ,那么我们需要定义更多的类型。我们可以通过添加接口来实现这一点 LoopFromSetBuilder , LoopToSetBuilder 以及 LoopAllSetBuilder :

interface LoopFromSetBuilder {
    LoopAllSetBuilder to(int to);
}

interface LoopToSetBuilder {
    LoopAllSetBuilder from(int from);
}

interface LoopAllSetBuilder {
    void execute(Runnable runnable);
}

再加上方法上的小小调整 Loop ```
class Loop {
...
public static LoopFromSetBuilder from(int from) {
return new Builder().from(from);
}

public static LoopToSetBuilder to(int to) {
    return new Builder().to(to);
}
...

}

让 `Builder` 实现这些接口:

public static class Builder implements LoopFromSetBuilder, LoopToSetBuilder, LoopAllSetBuilder {
...
}

ideone演示
我们排除了用户呼叫的可能性 `from(...)` 以及 `to(...)` 多次。
我对构建那些“复杂”的fluent api没有更多的经验,但我认为构建这样一个api的过程可能会非常痛苦。对于小例子,如这里所示,我们可能可以拒绝设置相同的变量可变时间,但如果参数更多,则会显得相当混乱(可能的状态-因此-接口的顺序似乎是 `2^n` 哪里 `n` 是字段数。。。所以是的。
如果你对我的答案投赞成票,那么你也应该考虑对luk2302的答案投赞成票,因为我的答案的第一个解决方案与luk2302的解决方案非常相似,并且luk2302的答案发布的时间比我的早一点。
1aaf6o9v

1aaf6o9v2#

最好有一个 from 和非静态名称相同,但不支持。参数或名称必须不同。
因此,我将私有构造函数设为公共的,并添加第二个no args构造函数,以便调用可以变成:

new Loop().from(5).to(10).execute(...)
new Loop(5, 10).execute(...)

为了工作 from 以及 to 必须不再是静态的。然后你必须决定这些方法是否会改变 Loop 示例调用它们,或者如果它们返回新对象:

public Loop from(int from) {
    return new Loop(from, to);
}

public Loop to(int to) {
    return new Loop(from, to);
}

public Loop from(int from) {
    this.from = from; // no longer final
    return this;
}

public Loop to(int to) {
    this.to = to; // no longer final
    return this;
}

如果您想更进一步,可以将类重命名为 LoopBuilder 创建一个 build() 返回 Loop 像以前一样有田地,但没有 from 以及 to 方法,只是 execute 方法:

public static class Loop {

    private final int from;
    private final int to;

    public Loop(int from, int to) {
        this.from = from;
        this.to = to;
    }

    public void execute(Executable executable) {
        for (int i = from; i < to; i++) {
            executable.execute();
        }
    }

    public static LoopBuilder builder() {
        return new LoopBuilder();
    }
}

public static class LoopBuilder {
    private int from;
    private int to;

    public LoopBuilder from(int from) {
        this.from = from;
        return this;
    }

    public LoopBuilder to(int to) {
        this.to = to;
        return this;
    }

    public Loop build() {
        return new Loop(from, to);
    }
}

这个电话就会变成

Loop.builder().from(5).to(10).build().execute(...);

相关问题