Search code examples
javakotlinguice

What is a right design for a such injection?


I have two classes of a one interface:

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

TimeUtils binding is in the module A:

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

TimeUtilsSimulation binding is in the module B:

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

and these modules A and B are used in different binaries.

I injected TimeUtils in a common code like:

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

And now I have a problem that when I have a request to start simulation I need to set an initial time in the TimeUtilsSimulation object. I can do it like this:

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()
}

but it looks ugly. Can you suggest something to solve this bad design?


Solution

  • I don't know Kotlin, but pure OOP speaking, the best would be to define a TimeUtilsWrapper interface that extends TimeUtils and adds setStartTime(...) method. Then you would have 2 classes implementing this interface:

    • 1 that embeds a TimeUtils object with empty setStartTime() that delegates all other methods to the embedded object,
    • second that embeds a TimeUtilsSimulation and delegates all methods to it, including setStartTime().

    Then SomeClass method should have a property of type TimeUtilsWrapper instead of TimeUtils and onRequest(...) should just always call TimeUtilsWrapper's setStartTime(...).