gpt4 book ai didi

scala - 如何将构建器模式转换为功能实现?

转载 作者:行者123 更新时间:2023-12-04 08:31:26 25 4
gpt4 key购买 nike

grpc-java library 是一个很好的库示例,它利用通用构建器模式来创建具有特定属性的对象:

val sslContext = ???

val nettyChannel : NettyChannel =
NettyChannelBuilder
.forAddress(hostIp, hostPort)
.useTransportSecurity()
.sslContext(sslContext)
.build

给定一个使用这种模式的库,如何包装它以便提供适当的功能 API? 我想一个单子(monad)是合适的工具。

基本的第一次尝试如下所示:
val updateBuilder : (NettyChannelBuilder => Unit) => NettyChannelBuilder => NettyChannelBuilder = 
updateFunc => builder => {
updateFunc(builder)
builder
}

val addTransportSecurity : NettyChannelBuilder => Unit =
(_ : NettyChannelBuilder).useTransportSecurity()

val addSslContext : NettyChannelBuilder => Unit =
builder => {
val sslContext = ???
builder sslContext sslContext
}

虽然这个方法很冗长,但它至少允许组合:
 val builderPipeline : NettyChannelBuilder => NettyChannelBuilder =
updateBuilder(addTransportSecurity) andThen updateBuilder(addSslContext)

val nettyChannel =
builderPipeline(NettyChannelBuilder.forAddress(hostIp, hostPort)).build

一个约束:不使用 scalaz , cats ,或其他一些 3rd 方库。只有scala语言“东西”。

注意:grpc 只是一个示例用例,而不是问题的重点......

预先感谢您的考虑和回复。

最佳答案

我知道我们说不 cats et al.但我决定发布这个,首先,老实说,作为我自己的练习,其次,因为本质上这些库只是聚合了“常见”类型的函数构造和模式。

毕竟,您是否考虑过使用普通 Java/Scala 编写 HTTP 服务器,或者您会选择一个经过实战测试的现成服务器? (对不起传福音)

无论如何,如果你真的想要的话,你可以用你自己的一个本地实现来替换他们的重量级实现。

我将在下面介绍我想到的两个方案,第一个使用 Reader monad,第二个使用 State单子(monad)。我个人觉得第一种方法比第二种方法笨拙一些,但它们都不太好看。我想一个更有经验的从业者可以比我做得更好。

在此之前,我发现以下内容相当有趣:Semicolons vs Monads

编码:

我定义了Java Bean:

public class Bean {

private int x;
private String y;

public Bean(int x, String y) {
this.x = x;
this.y = y;
}

@Override
public String toString() {
return "Bean{" +
"x=" + x +
", y='" + y + '\'' +
'}';
}
}

和 build 者:
public final class BeanBuilder {
private int x;
private String y;

private BeanBuilder() {
}

public static BeanBuilder aBean() {
return new BeanBuilder();
}

public BeanBuilder withX(int x) {
this.x = x;
return this;
}

public BeanBuilder withY(String y) {
this.y = y;
return this;
}

public Bean build() {
return new Bean(x, y);
}
}

现在对于 scala 代码:
import cats.Id
import cats.data.{Reader, State}

object Boot extends App {

val r: Reader[Unit, Bean] = for {
i <- Reader({ _: Unit => BeanBuilder.aBean() })
n <- Reader({ _: Unit => i.withX(12) })
b <- Reader({ _: Unit => n.build() })
_ <- Reader({ _: Unit => println(b) })
} yield b

private val run: Unit => Id[Bean] = r.run
println("will come before the value of the bean")
run()


val state: State[BeanBuilder, Bean] = for {
_ <- State[BeanBuilder, BeanBuilder]({ b: BeanBuilder => (b, b.withX(13)) })
_ <- State[BeanBuilder, BeanBuilder]({ b: BeanBuilder => (b, b.withY("look at me")) })
bean <- State[BeanBuilder, Bean]({ b: BeanBuilder => (b, b.build()) })
_ <- State.pure(println(bean))
} yield bean

println("will also come before the value of the bean")
state.runA(BeanBuilder.aBean()).value
}

由于这些 monad 评估的惰性,输出是:
will come before the value of the bean
Bean{x=12, y='null'}
will also come before the value of the bean
Bean{x=13, y='look at me'}

关于scala - 如何将构建器模式转换为功能实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52856084/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com