pengantar
Pengembangan Android untuk DI secara tradisional menggunakan Dagger 2 , kerangka kerja pembuatan kode yang sangat kuat. Tetapi ada masalah: sulit bagi pemula untuk menggunakannya. Prinsip DI itu sendiri sederhana dan mudah, tetapi Belati mempersulitnya. Anda dapat mengeluh tentang penurunan mutlak dalam literasi programmer, tetapi masalahnya tidak akan hilang dari ini.
Dengan munculnya Kotlin, menjadi mungkin untuk menulis hal-hal yang nyaman yang hampir tidak mungkin menggunakan Java. Salah satu dari hal-hal ini adalah Koin , yang bukan DI, tetapi Service Locator, yang diperlakukan oleh banyak orang sebagai anti-pola , itulah sebabnya banyak orang pada dasarnya tidak menggunakannya. Tetapi sia-sia, karena memiliki API yang sangat ringkas yang menyederhanakan penulisan dan pemeliharaan kode.
Dalam artikel ini, saya ingin membantu para pemula mencari tahu perbedaan antara Dependency Injection dan Service Locator, tetapi bukan Koin itu sendiri.
Ketergantungan injeksi
Pertama-tama, apa itu Injeksi Ketergantungan? Dengan kata sederhana, ini adalah ketika suatu objek menerima dependensi dari luar, daripada membuat atau mengekstraksi sendiri. Saya akan memberi contoh. Misalkan kita memiliki antarmuka Engine
, implementasinya, dan juga kelas Car
yang bergantung pada Engine
. Tanpa DI, akan terlihat seperti ini
interface Engine
class DefaultEngine: Engine
class Car {
private val engine: Engine = DefaultEngine()
}
fun main() {
val car = Car()
}
Jika kita menulis ulang kelas Car
menggunakan pendekatan DI, maka ini bisa terjadi:
class Car(private val engine: Engine)
fun main() {
val car = Car(DefaultEngine())
}
Sederhana - kelas Car
tidak tahu dari mana implementasi berasal Engine
, sementara mengganti implementasi ini sangat mudah, hanya meneruskannya ke konstruktor.
Pencari layanan
Service Locator. – , . Koin ServiceLocator, , API.
object ServiceLocator {
fun <reified T> register(factory: () -> T) { ... }
fun <reified T> resolve(): T { ... }
}
, . :
interface Engine
class DefaultEngine: Engine
class Car {
private val engine: Engine = ServiceLocator.resolve()
}
fun main() {
ServiceLocator.register<Engine> { DefaultEngine() }
val car = Car()
}
DI, Car
, , – Car
, . :
interface ServiceLocator {
fun <reified T> register(factory: () -> T)
fun <reified T> resolve(): T
}
class DefaultServiceLocator: ServiceLocator { ... }
class Car(private val serviceLocator: ServiceLocator) {
private val engine = serviceLocator.resolve<Engine>()
}
fun main() {
val serviceLocator = DefaultServiceLocator()
serviceLocator.register<Engine> { DefaultEngine() }
val car = Car(serviceLocator)
}
, Car
, . .. . :
class Car(private val engine: Engine)
fun main() {
ServiceLocator.register<Engine> { DefaultEngine() }
val car = Car(ServiceLocator.resolve<Engine>())
}
Ini adalah Injeksi Ketergantungan murni. Dengan Koin, akan terlihat seperti ini:
interface Engine
class DefaultEngine: Engine
class Car(private val engine: Engine)
fun carModule() = module {
factory<Engine> { DefaultEngine() }
factory { Car(get<Engine>()) }
}
fun main() {
val koin = startKoin {
modules(carModule())
}.koin
val car = koin.get<Car>()
}
Sayangnya, kita masih perlu menghubungi Koin untuk dependensi, tetapi ini sama sekali tidak bertentangan dengan prinsip-prinsip Injeksi Ketergantungan.
MEMPERBARUI Atas permintaankranid Saya akan memberikan contoh paling sederhana pada Dagger 2.
interface Engine
class DefaultEngine: Engine
class Car @Inject constructor(private val engine: Engine)
@Module
class AppModule {
@Provides
fun provideEngine(): Engine = DefaultEngine()
}
@Component(modules = [AppModule.class])
interface AppComponent {
fun car(): Car
}
fun main() {
val daggerComponent = DaggerAppComponent.create()
val car = daggerComponent.car()
}