Sobes.tech
Middle+

Jak użycie wzorca Singleton może naruszać zasady polimorfizmu?

sobes.tech AI

Odpowiedź od AI

Singleton ogranicza tworzenie instancji klasy do jednego obiektu. Polimorfizm natomiast zakłada możliwość pracy z obiektami różnych klas przez wspólny interfejs lub klasę bazową.

Naruszenie występuje, gdy kod klienta jest sztywno powiązany z konkretną klasą Singleton, zamiast pracować z abstrakcją (protokołem lub klasą bazową). W takim przypadku nie można podmienić innego, alternatywnego obiektu, który implementuje tę samą funkcjonalność, ponieważ klient oczekuje dokładnie instancji Singleton.

// Złe użycie - klient bezpośrednio zależy od ConcreteSingleton
class ConcreteSingleton {
    static let shared = ConcreteSingleton()
    private init() {}

    func performAction() {
        print("Wykonywanie akcji z ConcreteSingleton")
    }
}

// Klient
func clientFunction() {
    // Sztywne powiązanie z ConcreteSingleton
    ConcreteSingleton.shared.performAction()
}

// Dobre użycie - klient zależy od protokołu
protocol Service {
    func performAction()
}

class RealService: Service {
    func performAction() {
        print("Wykonywanie akcji z RealService")
    }
}

class MockService: Service {
    func performAction() {
        print("Wykonywanie akcji z MockService")
    }
}

// Singleton do dostarczania implementacji przez protokół (opcjonalnie, można użyć DI)
class ServiceProvider {
    static let shared = ServiceProvider()
    private init() {}

    private var currentService: Service = RealService()

    func setService(_ service: Service) {
        currentService = service
    }

    func getService() -> Service {
        return currentService
    }
}

// Klient
func flexibleClientFunction() {
    // Praca przez abstrakcję (protokół)
    let service = ServiceProvider.shared.getService()
    service.performAction()
}

// Przykłady polimorfizmu z elastycznym klientem
// ServiceProvider.shared.setService(MockService())
// flexibleClientFunction() będzie używać MockService

W ten sposób, bezpośrednie korzystanie z właściwości statycznej shared Singletona w kodzie klienta obniża elastyczność i utrudnia podmianę implementacji, co jest kluczowym aspektem polimorfizmu przy pracy z różnymi typami obiektów przez wspólny interfejs. Rozwiązaniem jest korzystanie z instancji Singletona przez protokół lub klasę bazową.