这种注射的正确设计是什么?

What is a right design for a such injection?

我有两个类一个接口:

interface TimeUtils { ... }
class TimeUtilsImpl : TimeUtils { ... }
class TimeUtilsSimulation : TimeUtils { ... }

TimeUtils 绑定在模块 A:

bind(TimeUtils::class.java).to(TimeUtilsImpl::class.java).`in`(Singleton)

TimeUtilsSimulation 绑定在模块中 B:

bind(TimeUtils::class.java).to(TimeUtilsSimulation::class.java).`in`(Singleton)

这些模块 AB 用于不同的二进制文件。

我在一个普通代码中注入了 TimeUtils,例如:

class SomeClass @Inject constructor(
  private val timeUtils: TimeUtils
)

现在我有一个问题,当我有一个开始模拟的请求时,我需要在 TimeUtilsSimulation 对象中设置一个初始时间。我可以这样做:

class RequestHandler @Inject constructor(
  private val someObject: SomeClass
)
onRequest(simulationStartTime: LocalDateTime) {
   if (timeUtils instanceof TimeUtilsSimulation) {
       // Set start time in a singleton timeUtils object
       (timeUtils as TimeUtilsSimulation).setStartTime(simulationStartTime)
   }
   someObject.run()
}

但它看起来很难看。 你能提出一些建议来解决这个糟糕的设计吗?

也许将setStartTime添加到TimeUtils接口中而不在TimeUtilsImpl中实现?这完全取决于上下文。例如,对于单元测试,我认为您的解决方案会很好。但对于其他人来说,“正常”的业务逻辑似乎很可疑。这几乎就像界面没有真正正确地抽象概念

我不了解 Kotlin,但就纯 OOP 而言,最好是定义一个扩展 TimeUtils 并添加 setStartTime(...) 方法的 TimeUtilsWrapper 接口。那么你将有 2 类 实现这个接口:

  • 1 嵌入一个 TimeUtils 空对象 setStartTime() 将所有其他方法委托给嵌入的对象,
  • second 嵌入 TimeUtilsSimulation 并将所有方法委托给它,包括 setStartTime().

然后 SomeClass 方法应该有一个 属性 类型 TimeUtilsWrapper 而不是 TimeUtils 并且 onRequest(...) 应该总是调用 TimeUtilsWrapper' s setStartTime(...).