Singleton — bu nədir, iOS və Android-də sinifin tək nümunəsi

Müəllif: IT Sectr Dərc olunub: 2026-02-17 Oxuma vaxtı: 8 dəq

Singleton (təkliq) — sinifin yeganə nümunəsini təmin edən və ona qlobal giriş nöqtəsi təqdim edən yaradıcı nümunə. Singleton mobil inkişafda paylaşılan resurslar üçün geniş tətbiq olunur: şəbəkə müştəriləri, verilənlər bazaları, tənzimləmə menecerləri. Nümunə klassik GoF (1994) kitabında təsvir edilmişdir və ən tanınanlardan biri olaraq qalır. Ətraflı — Refactoring Guru: Singleton.

Əsas

  • Singleton — bütün tətbiq üçün sinifin bir nümunəsini təmin edir
  • Qlobal giriş nöqtəsi — statik xüsusiyyət shared və ya companion object
  • Thread safety — çoxiplikli mühitdə düzgün iş üçün sinxronizasiya tələb olunur
  • Tənqid — Singleton test etməyi çətinləşdirir və gizli asılılıqlar yaradır
  • Alternativlər — Dependency Injection, Service Locator Singleton-u əvəz etmək üçün

Singleton nədir: təkliq nümunəsinin mahiyyəti?

Singleton (təkliq) — 1994-cü ildə GoF (Gang of Four) tərəfindən təsvir edilən yaradıcı dizayn nümunəsi. Nümunə iki məsələni həll edir: sinif nümunəsinin yaradılmasını bir obyektlə məhdudlaşdırır və həmin obyektə qlobal giriş təmin edir. Singleton unikal olmalı resurslar üçün faydalıdır: sessiya fabriki, şəkil keşi, verilənlər bazası qoşulma meneceri, Crashlytics və ya Analytics müştərisi.

Singleton tətbiqi özəl konstruktor (xarici yaradılmanı qadağan edir), yeganə nümunə ilə statik sahə və statik giriş metodu (shared, instance, getInstance) tələb edir. Müştərilər obyektin yaradılması ilə məşğul olmadan Singleton.shared.method() çağırır. Nümunə iOS və Android-də populyardır: URLSession.shared, UserDefaults.standard, FirebaseApp.sharedInstance — bunların hamısı Singleton-dur. Lakin Singleton-un həddindən artıq istifadəsi Global State anti-nümunəsinə gətirib çıxarır.

Singleton problemləri — gizli asılılıqlar (siniflər Singleton obyektindən örtülü asılıdır), test etmənin çətinliyi (əlavə səy olmadan testdə nümunəni əvəz etmək mümkün deyil), Single Responsibility Principle-un pozulması (Singleton həm öz nümunəsini, həm də biznes məntiqini idarə edir). Müasir mobil inkişaf tək nümunələri idarə etmək üçün DI (Dagger, Hilt, Swinject) üstünlük verir — DI konteyneri obyekti bir dəfə yaradır və onu konstruktor vasitəsilə əlavə edir.

iOS-da Swift-də Singleton: shared və statik xüsusiyyətlər

Swift Singleton özəl başlatıcı ilə shared statik xüsusiyyəti vasitəsilə tətbiq edilir. Swift 3-dən etibarən, statik xüsusiyyətlərin ləng başladılması təminatlı olaraq iplik təhlükəsizdir — kompilyator dispatch_once vasitəsilə avtomatik sinxronizasiya əlavə edir. static let shared = Class() elan etmək və init()-i özəl etmək kifayətdir. Swift başlatmadan sonra tək iplikli giriş üçün əlavə sinxronizasiya tələb etmir.

swift
final class NetworkManager {
    // Thread-safe 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
    }
}

// İstifadə
let data = try await NetworkManager.shared.fetchData(from: url)

Apple Singleton — iOS SDK-da bir çox obyekt Singleton istifadə edir: UIApplication.shared, UIScreen.main, FileManager.default, NotificationCenter.default, UserDefaults.standard. Apple fiziki olaraq unikal olan xidmətlər üçün Singleton istifadə edir (bir ekran, bir tətbiq). Tərtibatçılar bu nümunəni öz xidmətləri üçün kopyalayırlar. SwiftUI-də Singleton-a qlobal giriş Environment və @EnvironmentObject ilə əvəz olunur, bu da test edilə bilənliyi yaxşılaşdırır.

Android-də Kotlin-də Singleton: companion object və object

Kotlin Singleton — ən sadə yol: object açar sözü ilk girişdə ləng başlatma ilə sinif-singleton elan edir. Kotlin object iplik təhlükəsizdir və əlavə sinxronizasiya tələb etmir. Konstruktor parametrləri olan Singleton lazımdırsa, lazy-delegat ilə companion object istifadə olunur. Android-də Singleton tez-tez Application konteksti və Application.onCreate() vasitəsilə başladılan xidmətlər üçün lazımdır.

kotlin
// Variant 1: object — parametrsiz sadə 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) }
}

// Variant 2: companion object — parametrlərlə 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 — Android-in bir çox sistem xidmətləri Singleton tətbiq edir: context.getSystemService(), Room.databaseBuilder(), Retrofit.Builder(). Nümunələrə SharedPreferences, MediaPlayer, AudioManager daxildir. Android tətbiqlərində Singleton tez-tez depolar, menecerlər və fabriklər üçün istifadə olunur. Google Singleton-u DI (Hilt, Koin) ilə əvəz etməyi tövsiyə edir, burada Singleton əhatəsi (Scope.Singleton və ya @Singleton) konteyner tərəfindən idarə olunur və sinif test edilə bilən qalır.

Thread safety: dispatch_once, synchronized və lock

Thread safety — çoxiplikli mühitdə Singleton üçün kritik tələb. Sinxronizasiya olmadan iki iplik eyni anda instance == null yoxlayıb iki nümunə yarada bilər. Həlli — ilk yaratmada bloklama və başlatmadan sonra sərbəst buraxma. Swift-də statik xüsusiyyətlər (static let) susmaya görə iplik təhlükəsizdir. Kotlin-də object iplik təhlükəsizdir. Kotlin-də Java üslubu üçün synchronized və ya @Volatile + double-check locking istifadə olunur.

DilMexanizmİplik təhlükəsizliyiLəng başlatma
Swiftstatic letdispatch_once (avtomatik)Bəli, ilk girişdə
Kotlin objectObject declarationSinif başlatıcısı iplik təhlükəsizdirBəli, ilk girişdə
Kotlin companionsynchronized + @VolatileDouble-checked lockingBəli, lazy və ya synchronized vasitəsilə
Javasynchronized + volatileDouble-checked lockingBəli, getInstance() daxilində

Double-checked locking — Singleton-un ləng başladılması üçün nümunə. Birinci yoxlama sinxronizasiya olmadan (nümunə artıq yaradılıbsa sürətli), ikincisi — synchronized daxilində (yalnız bir iplik tərəfindən yaratma). @Volatile bütün ipliklər üçün dəyişikliklərin görünməsini təmin edir. Volatile olmadan başqa bir iplik qismən yaradılmış obyekti görə bilər. Kotlin-də LazyThreadSafetyMode.SYNCHRONIZED ilə lazy-delegat avtomatik olaraq double-checked locking tətbiq edir.

Singleton vs Dependency Injection: nə vaxt istifadə etməli

Dependency Injection — tək nümunəni idarə etmək üçün Singleton-a alternativ. DI konteyneri (Dagger, Hilt, Koin, Swinject) obyekti Singleton əhatəsində bir dəfə yaradır və onu konstruktor vasitəsilə əlavə edir. Sinif öz Singleton statusu haqqında bilmir — bu konteyner tərəfindən qərar verilir. Kod test edilə bilən olur: testdə DI modulu mock modulu ilə əvəz olunur. DI-nin üstünlükləri: konstruktorda aşkar asılılıqlar, ləğv etmə imkanı, vahid həyat dövrü.

Singleton nə vaxt əsaslandırılır — sistem səviyyəli obyektlər: Crashlytics, Analytics, Logging. Bu xidmətlər AppDelegate/Application-da bir dəfə başladılır və hər yerdə istifadə olunur. DI onlar üçün həddindən artıqdır. Singleton həmçinin şəkil keşləri (NSCache, Coil, Glide) üçün əlverişlidir, burada qlobal giriş performansla əsaslandırılır. Qalan hər şey üçün DI üstünlük təşkil edir: asılılıqları görünən edir, test etmə və yenidənqurmanı sadələşdirir.

Hibrid yanaşma — testlər üçün ləğv etmə imkanı olan Singleton. Swift-də protokol + statik xüsusiyyət istifadə olunur, test onu əvəz edə bilər (məsələn, URLSession üçün URLProtocol vasitəsilə). Kotlin-də — refleksiya və ya setter vasitəsilə testin mock təyin etdiyi injectable xüsusiyyəti olan open class. Bu yanaşma Singleton-un sadəliyini qoruyur, lakin test üçün vasitələr verir. Google Android üçün Hilt tövsiyə edir, Apple iOS üçün DI tələb etmir — seçim komandadan asılıdır.

Tez-tez verilən suallar

Singleton — bu anti-nümunədir?

Xeyr, Singleton GoF nümunəsidir, lakin onun tez-tez səhv istifadəsi onu Global State anti-nümunəsinə çevirir. Singleton fiziki olaraq unikal resurslar (ekran, printer, fayl sistemi) üçün əsaslandırılır. Problemlər Singleton məlumatların idarə edilməsi üçün istifadə edildikdə yaranır: gizli asılılıqlar, test etmənin çətinliyi, Single Responsibility Principle-un pozulması. Müasir alternativ — Singleton əhatəsi ilə DI.

Singleton istifadə edən kodu necə test etməli?

Üç yanaşma: (1) protokol vasitəsilə — Singleton protokolu tətbiq edir, testlər tətbiqi əvəz edir; (2) DI vasitəsilə — Singleton konstruktor vasitəsilə asılılıq olaraq əlavə edilir; (3) reset-metod vasitəsilə — Singleton testlərdə vəziyyəti sıfırlamaq üçün metoda malikdir (yalnız test buildi üçün). Birinci yanaşma üstünlük təşkil edir, üçüncüsü — istehsal üçün təhlükəlidir. Swift testlərdə runtime manipulyasiyaları vasitəsilə shared xüsusiyyətini əvəz etməyə imkan verir.

Kotlin object Java Singleton-dan nə ilə fərqlənir?

Kotlin object — bayt kod səviyyəsində Singleton yaradan dil konstruksiyası. Java tətbiqindən fərqli olaraq özəl konstruktor və getInstance() ilə, object iplik təhlükəsizliyi, ləng başlatma və miras alma qadağasını təmin edir. Java Singleton çoxiplikli mühitdə düzgün iş üçün əl ilə sinxronizasiya (synchronized) və volatile tələb edir. Kotlin object — Android-də ən təhlükəsiz və yığcam yoldur.

Singleton-u miras almaq olarmı?

Singleton-u miras almaq nümunəni pozur: əgər Singleton sinfi miras alına bilirsə, alt sinif ikinci nümunə yarada bilər, unikallığı pozaraq. Swift-də final class miras almanı qadağan edir. Kotlin object miras alına bilməz (object — sealed). Variantlı Singleton lazımdırsa, Singleton əhatəsi ilə DI konteynerindən istifadə edin: bir nümunəni təmin edir və interfeyslər vasitəsilə miras almanı dəstəkləyir.

Android-də Singleton-a parametrləri necə ötürməli?

Parametrlər init(context: Application) və ya getInstance(param) vasitəsilə ötürülür. Kotlin object parametr qəbul etmir — fabrik metodu getInstance(param) ilə companion object istifadə edin. Hilt problemi həll edir: @Singleton + @Inject constructor(context: Application) — DI konteyneri Application kontekstini avtomatik əlavə edir. Retrofit müştərisi üçün parametrlər (baseUrl, interceptors) DI modulunda builder vasitəsilə ötürülür.

Nəticə

  • Singleton — tək nümunə və qlobal giriş ilə nümunə
  • Swift shared — kompilyatordan iplik təhlükəsizliyi ilə static let
  • Kotlin object — əlavə kod olmadan ləng başlatma
  • Thread safety — Java üçün double-checked locking, Swift/Kotlin üçün avtomatik
  • Apple SDK — UIApplication.shared, UserDefaults.standard, FileManager.default
  • Android SDK — Retrofit, Room, SharedPreferences Singleton menecerləri vasitəsilə
  • Alternativlər — test edilə bilən kod üçün Dependency Injection

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun