带有 Reactor mono 的构建器模式

发布于 2025-01-14 21:29:44 字数 1257 浏览 5 评论 0 原文

我有火箭课。我想通过构建器实例化一个火箭对象。我需要通过反应性存储库从数据库获取一些状态,但反应性存储库返回 Mono 或 Flux。如何使用 Mono 和 Flux 正确地将状态注入到构建器中。这是我尝试过的。

public class Rocket {

  private String engine;
  private String fuel;

  public Rocket(Builder builder) {
    engine = builder.getEngine();
    fuel = builder.getFuel();
  }

  public static class Builder {

    private String engine;
    protected Mono<String> engineCollector;

    private String fuel;
    protected Mono<String> fuelCollector;

    public Builder() {
    }

    protected Builder setEngine(Mono<String> engineCollector) {
      this.engineCollector = engineCollector.doOnNext((collect) -> {
        this.engine = collect;
      });
      return this;
    }

    private Builder setFuel(Mono<String> fuelCollector) {
      this.fuelCollector = fuelCollector.doOnNext((collect) -> {
        this.engine = collect;
      });
      return this;
    }

    public String getEngine() {
      return this.engine;
    }

    public String getFuel() {
      return this.fuel;
    }

    public Rocket build() {
      return engineCollector
        .flatMap(s -> fuelCollector)
        .then(Mono.just(new Rocket(this)))
        .block();
    }
  }
}

这种方法是好是坏什么是正确的方法

I have a rocket class. I want to instantiate a rocket object via builder. I need to get some state from database via reactive repository, but reactive repository returns either Mono or Flux. How do I properly inject state to the builder with Mono and Flux. Here's what I have tried.

public class Rocket {

  private String engine;
  private String fuel;

  public Rocket(Builder builder) {
    engine = builder.getEngine();
    fuel = builder.getFuel();
  }

  public static class Builder {

    private String engine;
    protected Mono<String> engineCollector;

    private String fuel;
    protected Mono<String> fuelCollector;

    public Builder() {
    }

    protected Builder setEngine(Mono<String> engineCollector) {
      this.engineCollector = engineCollector.doOnNext((collect) -> {
        this.engine = collect;
      });
      return this;
    }

    private Builder setFuel(Mono<String> fuelCollector) {
      this.fuelCollector = fuelCollector.doOnNext((collect) -> {
        this.engine = collect;
      });
      return this;
    }

    public String getEngine() {
      return this.engine;
    }

    public String getFuel() {
      return this.fuel;
    }

    public Rocket build() {
      return engineCollector
        .flatMap(s -> fuelCollector)
        .then(Mono.just(new Rocket(this)))
        .block();
    }
  }
}

Is this approach good or bad what's the proper way

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妄想挽回 2025-01-21 21:29:44

将构建器与响应式 API 结合起来的一种方法如下

Mono.just(Rocket.builder())
        .flatMap(builder ->
                engineCollector()
                        .map(builder::engine)
                        .thenReturn(builder)
        )
        .flatMap(builder ->
                fuelCollector()
                        .map(builder::fuel)
                        .thenReturn(builder)
        )
        .map(builder -> builder.build());

@Builder
class Rocket {
    private String engine;
    private String fuel;
}

Mono<String> engineCollector() {
...
}
    
Mono<String> fuelCollector() {
...
}

One way to combine builder with reactive API is the following

Mono.just(Rocket.builder())
        .flatMap(builder ->
                engineCollector()
                        .map(builder::engine)
                        .thenReturn(builder)
        )
        .flatMap(builder ->
                fuelCollector()
                        .map(builder::fuel)
                        .thenReturn(builder)
        )
        .map(builder -> builder.build());

where

@Builder
class Rocket {
    private String engine;
    private String fuel;
}

Mono<String> engineCollector() {
...
}
    
Mono<String> fuelCollector() {
...
}
一个人的夜不怕黑 2025-01-21 21:29:44

正如我在评论中所说,尝试将 Mono 转换为非反应式类型的东西与使用反应式编程一开始是背道而驰的。

根据响应式范例,当您拥有 MonoMono 时,您不应该尝试创建 Rocket。您应该创建一个 Mono

现在,代码(注意,出于可读性目的,我将使用实际的名义类型而不仅仅是字符串)。我个人更喜欢 Mono::zip 操作。对于只有两个值的情况,您甚至不需要构建器:

public class Rocket {
    ....
    public Rocket(Engine engine, FuelTank fuel) {
        ....
    }
    ....
}

Mono<Engine> engine = repo.getRocketEngine();
Mono<FuelTank> tank = repo.getRocketFuelTank();

Mono<Rocket> rocket = Mono.zip(engine, tank, Rocket::new);

当您确实有两个以上的属性时,这会变得更加复杂,但仍然非常简单。例如,假设您的火箭由三个部分组成:NoseConeEngineFuelTank,而不是两个部分。好吧,Mono::zip 为我们提供了 生成元组的覆盖,具有最多八个

Mono<NoseCone> cone = repo.getRocketNoseCone();
Mono<Engine> engine = repo.getRocketEngine();
Mono<FuelTank> tank = repo.getRocketFuelTank();

Mono<Tuple3<NoseCone, Engine, FuelTank>> builderStage1 = Mono.zip(cone, engine, tank);

Mono<Rocket> rocket = builderStage1.map(tuple -> {
    NoseCone coneValue = tuple.getT1();
    Engine engineValue = tuple.getT2();
    FuelTank tankValue = tuple.getT3();

    return Rocket.builder()
        .engine(engineValue)
        .fuel(tankValue)
        .noseCone(coneValue)
        .build();
});

或者,稍微缩短最后几行代码并摆脱丑陋的长类型签名:

Mono<Rocket> rocket = Mono.zip(cone, engine, tank).map(tuple -> Rocket.builder()
    .noseCone(tuple.getT1())
    .engine(tuple.getT2())
    .fuel(tuple.getT3))
    .build()
);

As I said, in the comment, trying to convert Mono into something that is is not a reactive type kind of flies in the face of using reactive programming to begin with.

According to reactive paradigm, you shouldn't try to create Rocket when you have Mono<Engine> and Mono<FuelTank>. You should be creating a Mono<Rocket>, instead.

Now, the code (note, that I would use the actual nominal types instead of just strings, for readability purposes). I personally would prefer the Mono::zip operation for most of cases you describe. For the case of just two values, you would not even need the builder:

public class Rocket {
    ....
    public Rocket(Engine engine, FuelTank fuel) {
        ....
    }
    ....
}

Mono<Engine> engine = repo.getRocketEngine();
Mono<FuelTank> tank = repo.getRocketFuelTank();

Mono<Rocket> rocket = Mono.zip(engine, tank, Rocket::new);

When you do have more than two properties, this becomes a little more involved, but still pretty straigntforward. For example, consider that your rocket has three parts: NoseCone, Engine, and FuelTank, instead of two. Well, the Mono::zip has us covered with overrides that produce tuples, having arity of up to eight:

Mono<NoseCone> cone = repo.getRocketNoseCone();
Mono<Engine> engine = repo.getRocketEngine();
Mono<FuelTank> tank = repo.getRocketFuelTank();

Mono<Tuple3<NoseCone, Engine, FuelTank>> builderStage1 = Mono.zip(cone, engine, tank);

Mono<Rocket> rocket = builderStage1.map(tuple -> {
    NoseCone coneValue = tuple.getT1();
    Engine engineValue = tuple.getT2();
    FuelTank tankValue = tuple.getT3();

    return Rocket.builder()
        .engine(engineValue)
        .fuel(tankValue)
        .noseCone(coneValue)
        .build();
});

Or, to shorten the last few lines of code a little bit and get rid of ugly long type signatures:

Mono<Rocket> rocket = Mono.zip(cone, engine, tank).map(tuple -> Rocket.builder()
    .noseCone(tuple.getT1())
    .engine(tuple.getT2())
    .fuel(tuple.getT3))
    .build()
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文