Singleton — co to je, jediná instance třídy v iOS a Android

Autor: IT Sectr Publikováno: 2026-02-17 Doba čtení: 8 min

Singleton — vytvářecí vzor, který zaručuje jedinou instanci třídy a poskytuje globální přístupový bod k ní. Singleton je široce používán v mobilním vývoji pro sdílené zdroje: síťové klienty, databáze, správce nastavení. Vzor byl popsán v klasické knize GoF (1994) a zůstává jedním z nejznámějších. Více — na Refactoring Guru: Singleton.

Hlavní

  • Singleton — zaručuje jednu instanci třídy v celé aplikaci
  • Globální přístupový bod — statická vlastnost shared nebo companion object
  • Thread safety — vyžaduje synchronizaci pro správnou práci ve vícevláknovém prostředí
  • Kritika — Singleton ztěžuje testování a vytváří skryté závislosti
  • Alternativy — Dependency Injection, Service Locator pro nahrazení Singleton

Co je Singleton: podstata vzoru singleton?

Singleton — vytvářecí vzor popsaný GoF (Gang of Four) v roce 1994. Vzor řeší dva úkoly: omezuje vytváření instance třídy na jeden objekt a poskytuje globální přístup k tomuto objektu. Singleton je užitečný pro zdroje, které musí být jedinečné: továrna na relace, mezipaměť obrázků, správce připojení k databázi, klient Crashlytics nebo Analytics.

Implementace Singleton vyžaduje soukromý konstruktor (zakazuje externí vytváření), statické pole s jedinou instancí a statickou přístupovou metodu (shared, instance, getInstance). Klienti volají Singleton.shared.method() bez starosti o vytváření objektu. Vzor je populární v iOS a Android: URLSession.shared, UserDefaults.standard, FirebaseApp.sharedInstance — všechno jsou to Singletony. Nadměrné používání Singleton však vede k anti-vzoru Global State.

Problémy Singleton — skryté závislosti (třídy implicitně závisí na objektu Singleton), obtížnost testování (instanci nelze v testu nahradit bez dalšího úsilí), porušení Single Responsibility Principle (Singleton spravuje jak svou instanci, tak obchodní logiku). Moderní mobilní vývoj preferuje DI (Dagger, Hilt, Swinject) pro správu jediných instancí — DI kontejner vytvoří objekt jednou a vloží ho přes konstruktor.

Singleton v iOS na Swift: shared a statické vlastnosti

Swift Singleton je implementován přes statickou vlastnost shared s privátním inicializátorem. Od Swift 3 je líná inicializace statických vlastností zaručeně vláknově bezpečná — kompilátor automaticky přidá synchronizaci přes dispatch_once. Stačí deklarovat static let shared = Class() a nastavit init() jako privátní. Swift nevyžaduje další synchronizaci pro jednovláknový přístup po inicializaci.

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
    }
}

// Použití
let data = try await NetworkManager.shared.fetchData(from: url)

Apple Singleton — v iOS SDK mnoho objektů používá Singleton: UIApplication.shared, UIScreen.main, FileManager.default, NotificationCenter.default, UserDefaults.standard. Apple používá Singleton pro služby, které jsou fyzicky jedinečné (jedna obrazovka, jedna aplikace). Vývojáři kopírují tento vzor pro své služby. V SwiftUI je globální přístup k Singleton nahrazen Environment a @EnvironmentObject, což zlepšuje testovatelnost.

Singleton v Android na Kotlin: companion object a object

Kotlin Singleton — nejjednodušší způsob: klíčové slovo object deklaruje třídu-singleton s línou inicializací při prvním přístupu. Kotlin object je vláknově bezpečný a nevyžaduje další synchronizaci. Pokud je potřeba Singleton s parametry konstruktoru, použije se companion object s lazy delegátem. V Android je Singleton často nezbytný pro kontext Application a služby inicializované přes Application.onCreate().

kotlin
// Varianta 1: object — jednoduchý Singleton bez parametrů
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) }
}

// Varianta 2: companion object — Singleton s parametry
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 — mnoho systémových služeb Android implementuje Singleton: context.getSystemService(), Room.databaseBuilder(), Retrofit.Builder(). Příklady zahrnují SharedPreferences, MediaPlayer, AudioManager. V Android aplikacích se Singleton často používá pro repozitáře, správce a továrny. Google doporučuje nahradit Singleton DI (Hilt, Koin), kde je Singleton rozsah (Scope.Singleton nebo @Singleton) spravován kontejnerem a třída zůstává testovatelná.

Thread safety: dispatch_once, synchronized a lock

Thread safety — kritický požadavek pro Singleton ve vícevláknovém prostředí. Bez synchronizace mohou dvě vlákna současně zkontrolovat instance == null a vytvořit dvě instance. Řešení — uzamčení při prvním vytvoření a uvolnění po inicializaci. Ve Swift jsou statické vlastnosti (static let) standardně vláknově bezpečné. V Kotlin je object vláknově bezpečný. Pro Java styl v Kotlin se používá synchronized nebo @Volatile + double-check locking.

JazykMechanismusVláknová bezpečnostLíná inicializace
Swiftstatic letdispatch_once (automatické)Ano, při prvním přístupu
Kotlin objectObject declarationInicializátor třídy je vláknově bezpečnýAno, při prvním přístupu
Kotlin companionsynchronized + @VolatileDouble-checked lockingAno, přes lazy nebo synchronized
Javasynchronized + volatileDouble-checked lockingAno, v getInstance()

Double-checked locking — vzor pro línou inicializaci Singleton. První kontrola bez synchronizace (rychlá, pokud instance již existuje), druhá — uvnitř synchronized (vytvoření pouze jedním vláknem). @Volatile zaručuje viditelnost změn pro všechna vlákna. Bez volatile může jiné vlákno vidět částečně vytvořený objekt. V Kotlin lazy delegát s LazyThreadSafetyMode.SYNCHRONIZED automaticky implementuje double-checked locking.

Singleton vs Dependency Injection: kdy použít

Dependency Injection — alternativa k Singleton pro správu jediné instance. DI kontejner (Dagger, Hilt, Koin, Swinject) vytvoří objekt jednou v Singleton rozsahu a vloží ho přes konstruktor. Třída neví o svém Singleton statusu — to rozhoduje kontejner. Kód se stává testovatelným: v testu je DI modul nahrazen mock modulem. Výhody DI: explicitní závislosti v konstruktoru, možnost přepsání, jednotný životní cyklus.

Kdy je Singleton oprávněný — objekty systémové úrovně: Crashlytics, Analytics, Logging. Tyto služby jsou inicializovány jednou v AppDelegate/Application a používány všude. DI je pro ně nadbytečný. Singleton je také vhodný pro mezipaměti obrázků (NSCache, Coil, Glide), kde je globální přístup ospravedlněn výkonem. Pro všechno ostatní je DI preferovanější: činí závislosti viditelnými, zjednodušuje testování a refaktorování.

Hybridní přístup — Singleton s možností přepsání pro testy. Ve Swift se používá protokol + statická vlastnost, kterou může test nahradit (např. přes URLProtocol pro URLSession). V Kotlin — otevřená třída s injectable vlastností, kde test nastaví mock přes reflexi nebo setter. Tento přístup zachovává jednoduchost Singleton, ale poskytuje nástroje pro testování. Google doporučuje Hilt pro Android, Apple nevnucuje DI pro iOS — volba závisí na týmu.

Často kladené dotazy

Je Singleton anti-vzor?

Ne, Singleton je vzor GoF, ale jeho časté nesprávné použití ho mění na anti-vzor Global State. Singleton je oprávněný pro fyzicky jedinečné zdroje (obrazovka, tiskárna, souborový systém). Problémy vznikají, když je Singleton používán pro správu dat: skryté závislosti, obtížnost testování, porušení Single Responsibility Principle. Moderní alternativa — DI s Singleton rozsahem.

Jak testovat kód používající Singleton?

Tři přístupy: (1) přes protokol — Singleton implementuje protokol, testy nahrazují implementaci; (2) přes DI — Singleton je vložen jako závislost přes konstruktor; (3) přes reset metodu — Singleton má metodu pro resetování stavu v testech (pouze pro testovací sestavení). První přístup je preferovaný, třetí — nebezpečný pro produkci. Swift umožňuje nahradit vlastnost shared pomocí runtime manipulací v testech.

Čím se liší Kotlin object od Java Singleton?

Kotlin object — jazyková konstrukce, která vytváří Singleton na úrovni bytekódu. Na rozdíl od Java implementace s privátním konstruktorem a getInstance(), object zaručuje vláknovou bezpečnost, línou inicializaci a zákaz dědičnosti. Java Singleton vyžaduje ruční synchronizaci (synchronized) a volatile pro správnou funkci ve vícevláknovém prostředí. Kotlin object — nejbezpečnější a nejstručnější způsob v Android.

Lze Singleton dědit?

Dědění Singleton porušuje vzor: pokud lze třídu Singleton dědit, podtřída může vytvořit druhou instanci, čímž poruší jedinečnost. Ve Swift final class zakazuje dědičnost. Kotlin object nelze dědit (object — sealed). Pokud je potřeba Singleton s variabilitou, použijte DI kontejner s Singleton rozsahem: zaručuje jednu instanci a podporuje dědičnost přes rozhraní.

Jak předat parametry Singleton v Android?

Parametry se předávají přes init(context: Application) nebo getInstance(param). Kotlin object nepřijímá parametry — použijte companion object s tovární metodou getInstance(param). Hilt řeší problém: @Singleton + @Inject constructor(context: Application) — DI kontejner vloží kontext Application automaticky. Pro retrofit klienta se parametry (baseUrl, interceptors) předávají přes builder v DI modulu.

Shrnutí

  • Singleton — vzor s jedinou instancí a globálním přístupem
  • Swift shared — static let s vláknovou bezpečností od kompilátoru
  • Kotlin object — líná inicializace bez dalšího kódu
  • Thread safety — double-checked locking pro Java, automatické pro Swift/Kotlin
  • Apple SDK — UIApplication.shared, UserDefaults.standard, FileManager.default
  • Android SDK — Retrofit, Room, SharedPreferences přes Singleton správce
  • Alternativy — Dependency Injection pro testovatelný kód

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také