Skip to content

Instantly share code, notes, and snippets.

@pyricau
Last active January 17, 2024 08:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pyricau/aca9d9f7091942d8ecac3d769133c205 to your computer and use it in GitHub Desktop.
Save pyricau/aca9d9f7091942d8ecac3d769133c205 to your computer and use it in GitHub Desktop.
A Dependency Injection Framework that fits in a toot: https://androiddev.social/@py/111769799220786590
class CoffeeLogger {
fun log(msg: String) {
println(msg)
}
}
interface Heater {
fun on()
fun off()
val isHot: Boolean
}
class ElectricHeater(private val logger: CoffeeLogger) : Heater {
override var isHot = false
private set
override fun on() {
isHot = true
logger.log("~ ~ ~ heating ~ ~ ~")
}
override fun off() {
isHot = false
}
}
interface Pump {
fun pump()
}
class Thermosiphon(
private val logger: CoffeeLogger,
private val heater: Heater
) : Pump {
override fun pump() {
if (heater.isHot) {
logger.log("=> => pumping => =>")
}
}
}
class CoffeeMaker(
private val logger: CoffeeLogger,
private val heater: Heater,
private val pump: Pump
) {
fun brew() {
heater.on()
pump.pump()
logger.log(" [_]P coffee! [_]P ")
heater.off()
}
}
class Linker {
val factories = mutableMapOf<Class<out Any?>, Linker.() -> Any?>()
}
inline fun <reified T> Linker.install(noinline factory: Linker.() -> T) {
factories[T::class.java] = factory
}
inline fun <reified T> Linker.get(): T {
return factories.getValue(T::class.java)() as T
}
inline fun <reified T> Linker.installSingleton(noinline factory: Linker.() -> T) {
var instance = UNINITIALIZED
install {
if (instance === UNINITIALIZED) {
instance = factory()
}
instance as T
}
}
var UNINITIALIZED: Any? = Any()
fun main() {
val logModule = Linker()
logModule.installSingleton {
CoffeeLogger()
}
val partsModule = Linker()
partsModule.installSingleton<Heater> {
ElectricHeater(get())
}
partsModule.install<Pump> {
Thermosiphon(get(), get())
}
val appModule = Linker()
appModule.install {
CoffeeMaker(get(), get(), get())
}
appModule.factories += logModule.factories + partsModule.factories
val maker = appModule.get<CoffeeMaker>()
maker.brew()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment