Kotlin中惰性默认参数的模式

rbl8hiat  于 2022-12-04  发布在  Kotlin
关注(0)|答案(2)|浏览(117)

我发现自己经常编写依赖于某些可能很昂贵的东西的类,例如WebClient。我希望这个依赖关系是一个参数,以获得最大的灵活性和可测试性。我发现了以下实现这一点的方法,但不确定选择哪一种。

选项A:构造函数中的空检查

class MyWebAppClient(webclient: WebClient? = null) {

    private val webclient: WebClient

    init {
        this.webclient = webclient ?: generateMyWebAppClient()
    }
    ...
}

用法示例:

MyWebAppClient()
MyWebAppClient(webclient)

选项B:lambda生成参数

class MyWebAppClient(private val webclient: () -> WebClient = { generateMyWebAppClient()}) {
    ...
}

用法示例:

MyWebAppClient()
MyWebAppClient({ webclient })
MyWebAppClient { webclient }

选项C:初始化默认参数

class MyWebAppClient(private val webclient: WebClient = generateMyWebAppClient()) {
    ...
}

用法示例:

MyWebAppClient()
MyWebAppClient(webclient)

问题

除了可读性上的明显差异之外,这些方法是否有任何优点或缺点?这些方法是否会带来内存泄漏或其他意外行为的风险?
我最喜欢的是选项C,因为它最容易读写。快速测试也没有发现任何意外的行为。我只是有点犹豫,因为Python中类似的代码会在函数被解析时调用函数,而不是在执行时。

fsi0uk1n

fsi0uk1n1#

选项B是惰性加载对象,当涉及到性能时,这是一种可行的方法。如果你想提高可测试性,你可能需要引入Factory来创建你的对象。使用Factory不会减轻你的代码的惰性加载(如果你使用KotlinLazy)和构造函数中的lambda(可读性)。

class MyWebAppClient(private val webclientFactory: WebClientFactory) {

   private val webClient by lazy { webclientFactory.create() } 

}

在测试中,您可以提供自己的测试工厂实现来返回mock WebClient,也可以只模拟Factory来返回mock WebClient

ttcibm8c

ttcibm8c2#

Lazy值也可以作为参数从外部传递:

val webClient by lazy { webclientFactory.create() }

class MyWebAppClient(private val webClientProvider: Lazy<WebClient>) {

   fun connect() = webClientProvider.value.connect()

}

这允许在多个调用中重用单个惰性值,具体取决于其定义范围。

相关问题