In Kotlin, the idiomatic way to implement the Singleton pattern is to use an object declaration.
object AppConfig {
val appName = "MyApp"
fun printConfig() {
println("App name: $appName")
}
}
You use it directly by its name:
fun main() {
AppConfig.printConfig()
println(AppConfig.appName)
}
Kotlin guarantees that an object declaration:
- has exactly one instance
- is initialized lazily, when first accessed
- is thread-safe
- can contain properties, functions, initialization blocks, and implement interfaces
Example with initialization:
object DatabaseManager {
init {
println("DatabaseManager initialized")
}
fun connect() {
println("Connecting to database...")
}
}
Usage:
fun main() {
DatabaseManager.connect()
}
If you need a singleton that implements an interface:
interface Logger {
fun log(message: String)
}
object ConsoleLogger : Logger {
override fun log(message: String) {
println("[LOG] $message")
}
}
Usage:
fun main() {
ConsoleLogger.log("Application started")
}
So instead of writing a private constructor and static getInstance() method like in Java, Kotlin’s idiomatic singleton is simply:
object MySingleton {
fun doSomething() {
println("Doing something")
}
}
