Singleton Kalıbı
Coddy'nin Kotlin Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 42 / 57.
Tasarım deseni, tekrar tekrar ortaya çıkan bir tasarım problemine yönelik kanıtlanmış bir çözümdür. Singleton deseni, bir sınıfın tüm programın erişebileceği tam olarak bir örneğe sahip olmasını sağlar. Kotlin'de bir object bildirimi bir singleton'dır: ilk kullanımda bir kez oluşturulur ve birkaç iş parçacığı aynı anda başlasa bile güvenli bir şekilde oluşturulur:
object Settings {
var theme = "light"
var fontSize = 14
}
fun openEditor() = "editor in ${Settings.theme} theme"main içinde:
Settings.theme = "dark"
println(openEditor())
println(Settings.fontSize)Çıktı:
editor in dark theme
14Singleton, programun farklı bölümlerinin paylaştığı durumu tutar. Bu durumu gizli tutun ve yalnızca metotlar aracılığıyla değiştirin; böylece her değişiklik aynı kurallardan geçer:
object Metrics {
private val hits = mutableMapOf<String, Int>()
fun hit(page: String) { hits[page] = (hits[page] ?: 0) + 1 }
fun report() = hits.entries.joinToString { "${it.key}=${it.value}" }
}
fun home() = Metrics.hit("home")
fun about() = Metrics.hit("about")main içinde:
home(); about(); home()
println(Metrics.report())Çıktı:
home=2, about=1Tek örneğin kurulum verilerine ihtiyaç duyduğu durumda, private constructor içeren bir sınıf, ilk istekte bunu companion object içinde oluşturabilir ve sonrasında aynı örneği döndürebilir:
class Database private constructor(val url: String) {
companion object {
private var instance: Database? = null
fun connect(url: String): Database =
instance ?: Database(url).also { instance = it }
}
}main içinde:
val a = Database.connect("db://main")
val b = Database.connect("db://other")
println(a === b)
println(b.url)Çıktı:
true
db://mainSingleton'ları ölçülü kullanın. Bir singleton global durumdur: herhangi bir kod onu değiştirebilir; bu, ona kimin bağlı olduğunu gizler ve testler yeni bir kopyayla başlayamaz. Gerçekten program başına bir tane olması gereken şeyler için, örneğin yapılandırma veya günlükleyici için uygundurlar. Programın yalnızca bir bölümü bir nesneye ihtiyaç duyduğunda, onu bir arayüz olarak türlendirip parametre şeklinde aktarın; böylece bir test bunun yerine sahte bir nesne geçirebilir:
interface Clock { fun now(): Long }
object SystemClock : Clock { override fun now() = System.currentTimeMillis() }
class Session(private val clock: Clock) { // bağımlılık görünür
val started = clock.now()
}
val session = Session(SystemClock) // bir test sahte bir Clock geçirirGörev
KolayLogger singleton'ını tamamla. Değiştirilebilir bir minLevel'a sahiptir (debug, info, warn veya error; bu sırayla). Seviye en az minLevel olduğunda log(level, message), [WARN] disk low değerini saklar; aksi durumda mesajı dropped içinde sayar. Bu değer kod dışından okunabilir ancak değiştirilemez. entries, saklanan satırların salt okunur listesidir ve count(level), o seviyeye sahip kaç saklanan satır olduğunu döndürür.
Functions.kt içindeki yardımcı işlevler sağlanmıştır: başka bir dosyadan aynı Logger'a erişirler. Sağlanan kod minimum seviyeyi ve ardından level,message satırlarını okur, sonra her girdiyi ve errors: 1, dropped: 2 değerini yazdırır.
Kodun Logger.kt ve Functions.kt dosyalarına yazılmalıdır. Main.kt, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.
Kendin dene
fun main() {
// Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
val input = generateSequence(::readLine).toList()
Logger.minLevel = input[0]
for (line in input.drop(1)) {
val (level, message) = line.split(",", limit = 2)
when (level) {
"debug" -> debug(message)
"info" -> info(message)
"warn" -> warn(message)
else -> error(message)
}
}
for (e in Logger.entries) println(e)
println("errors: ${Logger.count("error")}, dropped: ${Logger.dropped}")
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Sınıflar ve Nesneler
Dosyalarla ÇalışmaSınıfları TanımlamaBirincil Yapıcılarinit Blokları ve Doğrulamaİkincil YapıcılarTekrar - Kütüphane Kartı4Kalıtım
Açık Sınıflar ve Alt SınıflarÜyeleri Geçersiz Kılmasuper ve YapıcılarSoyut SınıflarTekrar - Personel Dizini2Özellikler ve Kapsülleme
Özel ErişimcilerGörünürlük DeğiştiricileriÖzel Setter'larlazy ve lateinitTekrar - Banka Hesabı5Arayüzler
Arayüz BildirimleriVarsayılan MetotlarBirden Çok ArayüzTür Olarak ArayüzlerÖzet - Ödeme Yöntemleri8Generic'ler
Generic FonksiyonlarGeneric SınıflarTür Kısıtlamalarıin ve out ile VaryansTekrar - Öncelik Kuyruğu11Proje: Kütüphane Yönetimi
Kitaplar ve ÜyelerKitap Ödünç AlmaKendi başına pratik yap: Kotlin playground