Middle+
Zašto se Singleton obrazac smatra anti-obrazcem?
sobes.tech АИ
Одговор од АИ
Singleton krši SOLID principe i otežava testiranje:
- Kršenje principa jedinstvene odgovornosti (SRP): Klasa istovremeno odgovara za svoju logiku i za upravljanje svojim životnim ciklusom (kreiranje i pristup jedinstvenom primeru).
- Kršenje principa otvorenosti/zatvorenosti (OCP): Proširenje funkcionalnosti Singleton klase može biti otežano bez izmene njenog koda.
- Kršenje principa zamene Barbare Liskov (LSP): Podtipovi Singleton klase možda neće zadovoljiti ugovore osnovnog tipa zbog specifičnosti implementacije Singleton.
- Kršenje principa inverzije zavisnosti (DIP): Moduli zavise od konkretne implementacije Singleton, a ne od apstrakcija. To otežava zamenjivanje Singleton objekta sa mock ili stub za testiranje.
- Problemi sa testiranjem: Singleton instanca je globalno stanje, što otežava paralelno izvršavanje testova i izolaciju test scenarija. Teško je zameniti zavisnost od Singleton objekta.
- Skrivena zavisnost: Korišćenje Singleton skriva zavisnosti između modula, jer one nisu eksplicitno prosleđene.
- Problemi sa višestrukim nitima: Potreba za sinhronizacijom pristupa Singleton instanci u višedretvenom okruženju može dovesti do komplikacija u kodu i potencijalnih grešaka.
- Složenost u odlaganju: Upravljanje životnim ciklusom Singleton objekta i njegovo odlaganje može biti nejasno.
Umesto Singleton često je poželjno koristiti ubrizgavanje zavisnosti (Dependency Injection) ili Service Locator za upravljanje životnim ciklusom objekata i njihovim pristupom.
Primer tipične implementacije Singleton na Swift-u, koji demonstrira pomenute probleme:
// Singleton.swift
class DataManager {
static let shared = DataManager() // Globalna tačka pristupa, skriva zavisnost
private init() { // Zatvoren i inicijalizator, otežava kreiranje mock objekata
// Inicijalizacija resursa ili stanja
}
func fetchData() -> [String] {
// Logika za dobijanje podataka (npr. iz mreže ili baze podataka)
// Ova logika je povezana sa upravljanjem stanjem i pristupom, krši SRP
return ["Item 1", "Item 2"]
}
}
// Primer korišćenja
// Modul koji direktno zavisi od DataManager.shared
class ViewController {
func displayData() {
let data = DataManager.shared.fetchData() // Skrivena zavisnost
print(data)
}
}
// Testiranje ViewController-a postaje složenije:
// Kako zameniti DataManager.shared sa mock objektom?
// Kako izolovati testove ako je DataSourceManager.shared globalni?