Singleton — nedir bu, iOS ve Android'de sınıfın tek örneği

Yazar: IT Sectr Yayınlanma: 2026-02-17 Okuma süresi: 8 dk

Singleton (tekil) — bir sınıfın tek örneğini garanti eden ve ona genel erişim noktası sağlayan oluşturucu kalıptır. Singleton mobil geliştirmede paylaşılan kaynaklar (ağ istemcileri, veritabanları, ayar yöneticileri) için yaygın olarak kullanılır. Kalıp, klasik GoF kitabında (1994) tanımlanmıştır ve en tanınabilir kalıplardan biri olmaya devam etmektedir. Daha fazla bilgi için Refactoring Guru: Singleton adresini ziyaret edin.

Önemli Noktalar

  • Singleton — tüm uygulamada sınıfın bir örneğini garanti eder
  • Genel erişim noktası — statik özellik shared veya companion object
  • Thread safety — çoklu iş parçacığı ortamında doğru çalışma için senkronizasyon gerekli
  • Eleştiri — Singleton test etmeyi zorlaştırır ve gizli bağımlılıklar oluşturur
  • Alternatifler — Dependency Injection, Service Locator Singleton'ı değiştirmek için

Singleton nedir: tekil kalıbın özü?

Singleton — GoF (Gang of Four) tarafından 1994'te tanımlanan bir oluşturucu tasarım kalıbıdır. Kalıp iki sorunu çözer: bir sınıfın örneklenmesini tek bir nesneyle sınırlar ve bu nesneye genel erişim sağlar. Singleton, benzersiz olması gereken kaynaklar (oturum fabrikaları, görüntü önbellekleri, veritabanı bağlantı yöneticileri, Crashlytics veya Analytics istemcileri) için kullanışlıdır.

Singleton uygulaması özel bir yapıcı (dış oluşturmayı engeller), tek örnekle statik bir alan ve statik bir erişim yöntemi (shared, instance, getInstance) gerektirir. İstemciler, nesne oluşturmayı düşünmeden Singleton.shared.method() çağrısı yapar. Kalıp iOS ve Android'de popülerdir: URLSession.shared, UserDefaults.standard, FirebaseApp.sharedInstance — hepsi Singleton'dır. Ancak Singleton'ın aşırı kullanımı Global State anti-kalıbına yol açar.

Singleton sorunları — gizli bağımlılıklar (sınıflar örtük olarak Singleton nesnesine bağımlıdır), test karmaşıklığı (ek çaba olmadan testlerde örneğin değiştirilememesi), Tek Sorumluluk İlkesi'nin ihlali (Singleton hem kendi örneğini hem de iş mantığını yönetir). Modern mobil geliştirme, tek örnekleri yönetmek için DI'yi (Dagger, Hilt, Swinject) tercih eder — DI kapsayıcısı nesneyi bir kez oluşturur ve yapıcı aracılığıyla enjekte eder.

iOS'ta Swift ile Singleton: shared ve statik özellikler

Swift Singleton, özel bir başlatıcıya sahip statik bir shared özelliği aracılığıyla uygulanır. Swift 3'ten bu yana, statik özelliklerin geç başlatılmasının iş parçacığı güvenli olduğu garanti edilir — derleyici dispatch_once aracılığıyla otomatik olarak senkronizasyon ekler. static let shared = Class() bildirmek ve init()'i özel yapmak yeterlidir. Swift, başlatmadan sonra tek iş parçacıklı erişim için ek senkronizasyon gerektirmez.

swift
final class NetworkManager {
    // İş parçacığı güvenli Singleton
    static let shared = NetworkManager()

    private init() {
        URLSessionConfiguration.default.timeoutIntervalForRequest = 30
    }

    private var cache = NSCache<NSString, NSData>()

    func fetchData(from url: URL) async throws -> Data {
        let key = url.absoluteString as NSString
        if let cached = cache.object(forKey: key) {
            return cached as Data
        }
        let (data, _) = try await URLSession.shared.data(from: url)
        cache.setObject(data as NSData, forKey: key)
        return data
    }
}

// Kullanım
let data = try await NetworkManager.shared.fetchData(from: url)

Apple Singleton — birçok iOS SDK nesnesi Singleton kullanır: UIApplication.shared, UIScreen.main, FileManager.default, NotificationCenter.default, UserDefaults.standard. Apple, fiziksel olarak benzersiz hizmetler (bir ekran, bir uygulama) için Singleton kullanır. Geliştiriciler bu kalıbı kendi hizmetleri için kopyalar. SwiftUI'de, Singleton'a genel erişim Environment ve @EnvironmentObject ile değiştirilir ve test edilebilirlik iyileştirilir.

Android'de Kotlin ile Singleton: companion object ve object

Kotlin Singleton — en basit yol: object anahtar sözcüğü, ilk erişimde geç başlatma ile bir tekil sınıf bildirir. Kotlin object iş parçacığı güvenlidir ve ek senkronizasyon gerektirmez. Yapıcı parametreleri olan bir Singleton gerekiyorsa, bir lazy temsilcisi ile companion object kullanılır. Android'de Singleton, Application bağlamı ve Application.onCreate() aracılığıyla başlatılan hizmetler için genellikle gereklidir.

kotlin
// Seçenek 1: object — parametresiz basit Singleton
object AppPreferences {
    private val prefs = Application.instance
        .getSharedPreferences("app", Context.MODE_PRIVATE)

    var isFirstLaunch: Boolean
        get() = prefs.getBoolean("first_launch", true)
        set(value) = prefs.edit { putBoolean("first_launch", value) }
}

// Seçenek 2: companion object — parametreli Singleton
class ApiClient private constructor(baseUrl: String) {
    companion object {
        @Volatile
        private var instance: ApiClient? = null

        fun getInstance(baseUrl: String): ApiClient {
            return instance ?: this.synchronized {
                instance ?: ApiClient(baseUrl).also { instance = it }
            }
        }
    }

    fun request(endpoint: String): String { /* ... */ }
}

Android SDK Singleton — birçok Android sistem hizmeti Singleton uygular: context.getSystemService(), Room.databaseBuilder(), Retrofit.Builder(). Örnekler arasında SharedPreferences, MediaPlayer, AudioManager bulunur. Android uygulamalarında Singleton, depolar, yöneticiler ve fabrikalar için sıklıkla kullanılır. Google, Singleton'ı DI (Hilt, Koin) ile değiştirmeyi önerir; burada Singleton kapsamı (Scope.Singleton veya @Singleton) kapsayıcı tarafından yönetilirken sınıf test edilebilir kalır.

Thread safety: dispatch_once, synchronized ve lock

Thread safety — çoklu iş parçacığı ortamlarında Singleton için kritik bir gereksinimdir. Senkronizasyon olmadan, iki iş parçacığı aynı anda instance == null kontrolü yapabilir ve iki örnek oluşturabilir. Çözüm, ilk oluşturma sırasında kilitlemek ve başlatmadan sonra serbest bırakmaktır. Swift'te statik özellikler (static let) varsayılan olarak iş parçacığı güvenlidir. Kotlin'de object iş parçacığı güvenlidir. Kotlin'de Java stili için synchronized veya @Volatile + double-check locking kullanılır.

DilMekanizmaİş parçacığı güvenliğiGeç başlatma
Swiftstatic letdispatch_once (otomatik)Evet, ilk erişimde
Kotlin objectObject bildirimiSınıf başlatıcı iş parçacığı güvenliEvet, ilk erişimde
Kotlin companionsynchronized + @VolatileDouble-checked lockingEvet, lazy veya synchronized ile
Javasynchronized + volatileDouble-checked lockingEvet, getInstance() içinde

Double-checked locking — Singleton'ın geç başlatılması için bir kalıptır. İlk kontrol senkronizasyon olmadan (örnek zaten varsa hızlı), ikincisi synchronized içinde (yalnızca bir iş parçacığı tarafından oluşturma). @Volatile, tüm iş parçacıkları için değişikliklerin görünürlüğünü garanti eder. Volatile olmadan, başka bir iş parçacığı kısmen oluşturulmuş bir nesne görebilir. Kotlin'de, LazyThreadSafetyMode.SYNCHRONIZED ile lazy temsilcisi otomatik olarak double-checked locking uygular.

Singleton vs Dependency Injection: ne zaman kullanılmalı

Dependency Injection — tek örnekleri yönetmek için Singleton'a bir alternatiftir. Bir DI kapsayıcısı (Dagger, Hilt, Koin, Swinject) nesneyi Singleton kapsamında bir kez oluşturur ve yapıcı aracılığıyla enjekte eder. Sınıf, Singleton durumunu bilmez — kapsayıcı karar verir. Kod test edilebilir hale gelir: testlerde DI modülü bir mock modülü ile değiştirilir. DI avantajları: yapıcıda açık bağımlılıklar, geçersiz kılma yeteneği, birleşik yaşam döngüsü.

Singleton ne zaman haklıdır — sistem düzeyindeki nesneler: Crashlytics, Analytics, Logging. Bu hizmetler AppDelegate/Application'da bir kez başlatılır ve her yerde kullanılır. DI onlar için aşırıdır. Singleton ayrıca görüntü önbellekleri (NSCache, Coil, Glide) için de kullanışlıdır; burada genel erişim performansla haklı çıkarılır. Geri kalan her şey için DI tercih edilir: bağımlılıkları görünür kılar, test etmeyi ve yeniden düzenlemeyi basitleştirir.

Karma yaklaşım — testler için geçersiz kılınabilir Singleton. Swift'te, testlerin değiştirebileceği bir protokol + statik özellik (örneğin, URLSession için URLProtocol aracılığıyla). Kotlin'de, testlerin yansıma veya ayarlayıcı aracılığıyla bir mock ayarladığı enjekte edilebilir bir özelliğe sahip açık bir sınıf. Bu yaklaşım Singleton'ın basitliğini korur ancak test yetenekleri sağlar. Google Android için Hilt'i önerir, Apple iOS için DI'yi dayatmaz — seçim ekibe bağlıdır.

Sıkça Sorulan Sorular

Singleton bir anti-kalıp mıdır?

Hayır, Singleton bir GoF kalıbıdır, ancak sık yanlış kullanımı onu Global State anti-kalıbına dönüştürür. Singleton, fiziksel olarak benzersiz kaynaklar (ekran, yazıcı, dosya sistemi) için haklıdır. Singleton veri yönetimi için kullanıldığında sorunlar ortaya çıkar: gizli bağımlılıklar, test karmaşıklığı, Tek Sorumluluk İlkesi'nin ihlali. Modern alternatif, Singleton kapsamlı DI'dir.

Singleton kullanan kod nasıl test edilir?

Üç yaklaşım: (1) protokol aracılığıyla — Singleton bir protokol uygular, testler uygulamayı değiştirir; (2) DI aracılığıyla — Singleton yapıcı aracılığıyla bir bağımlılık olarak enjekte edilir; (3) reset yöntemi aracılığıyla — Singleton'ın testlerde durumu sıfırlamak için bir yöntemi vardır (yalnızca test yapıları için). İlk yaklaşım tercih edilir, üçüncüsü üretim için tehlikelidir. Swift, testlerde çalışma zamanı manipülasyonu yoluyla shared özelliğinin değiştirilmesine izin verir.

Kotlin object, Java Singleton'dan nasıl farklıdır?

Kotlin object, bayt kod düzeyinde Singleton oluşturan bir dil yapısıdır. Özel yapıcı ve getInstance() ile Java uygulamasının aksine, object iş parçacığı güvenliğini, geç başlatmayı garanti eder ve kalıtımı yasaklar. Java Singleton, çoklu iş parçacığı ortamlarında doğru çalışma için manuel senkronizasyon (synchronized) ve volatile gerektirir. Kotlin object, Android'de en güvenli ve özlü yoldur.

Singleton kalıtılabilir mi?

Singleton'ı kalıtmak kalıbı bozar: Bir Singleton sınıfı kalıtılabilirse, bir alt sınıf ikinci bir örnek oluşturarak benzersizliği ihlal edebilir. Swift'te, final class kalıtımı yasaklar. Kotlin object kalıtılamaz (object sealed'dır). Değişkenliğe sahip bir Singleton gerekiyorsa, Singleton kapsamlı bir DI kapsayıcısı kullanın: tek bir örneği garanti eder ve arayüzler aracılığıyla kalıtımı destekler.

Android'de Singleton'a parametreler nasıl iletilir?

Parametreler init(context: Application) veya getInstance(param) aracılığıyla iletilir. Kotlin object parametre kabul etmez — bir fabrika yöntemi getInstance(param) ile companion object kullanın. Hilt sorunu çözer: @Singleton + @Inject constructor(context: Application) — DI kapsayıcısı Application bağlamını otomatik olarak enjekte eder. Bir Retrofit istemcisi için parametreler (baseUrl, interceptors) DI modülündeki bir builder aracılığıyla iletilir.

Özet

  • Singleton — tek örnek ve genel erişime sahip kalıp
  • Swift shared — derleyici garantili iş parçacığı güvenliği ile static let
  • Kotlin object — ek kod olmadan geç başlatma
  • Thread safety — Java için double-checked locking, Swift/Kotlin için otomatik
  • Apple SDK — UIApplication.shared, UserDefaults.standard, FileManager.default
  • Android SDK — Retrofit, Room, SharedPreferences Singleton yöneticileriyle
  • Alternatifler — test edilebilir kod için Dependency Injection

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun