我发现自己经常编写依赖于某些可能很昂贵的东西的类,例如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中类似的代码会在函数被解析时调用函数,而不是在执行时。
2条答案
按热度按时间fsi0uk1n1#
选项B是惰性加载对象,当涉及到性能时,这是一种可行的方法。如果你想提高可测试性,你可能需要引入
Factory
来创建你的对象。使用Factory
不会减轻你的代码的惰性加载(如果你使用KotlinLazy
)和构造函数中的lambda(可读性)。在测试中,您可以提供自己的测试工厂实现来返回mock
WebClient
,也可以只模拟Factory
来返回mockWebClient
ttcibm8c2#
Lazy值也可以作为参数从外部传递:
这允许在多个调用中重用单个惰性值,具体取决于其定义范围。