Sobes.tech
Middle+

Come può l'uso del pattern Singleton violare i principi di polimorfismo?

sobes.tech AI

Risposta dell'AI

Il Singleton limita la creazione di istanze di una classe a un solo oggetto. Tuttavia, il polimorfismo implica la possibilità di lavorare con oggetti di diverse classi tramite un'interfaccia comune o una classe base.

La violazione si verifica quando il codice client si lega rigidamente a una singola classe Singleton, invece di lavorare con un'astrazione (protocollo o classe base). In questo caso, non è possibile sostituire con un altro oggetto alternativo che implementa la stessa funzionalità, poiché il client si aspetta esattamente un'istanza di Singleton.

// Uso scorretto - il client dipende direttamente da ConcreteSingleton
class ConcreteSingleton {
    static let shared = ConcreteSingleton()
    private init() {}

    func performAction() {
        print("Esecuzione di un'azione da ConcreteSingleton")
    }
}

// Client
func clientFunction() {
    // Dipendenza rigida da ConcreteSingleton
    ConcreteSingleton.shared.performAction()
}

// Uso corretto - il client dipende da un protocollo
protocol Service {
    func performAction()
}

class RealService: Service {
    func performAction() {
        print("Esecuzione di un'azione da RealService")
    }
}

class MockService: Service {
    func performAction() {
        print("Esecuzione di un'azione da MockService")
    }
}

// Singleton per fornire implementazione tramite protocollo (opzionale, si può usare 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
    }
}

// Client
func flexibleClientFunction() {
    // Lavoro tramite astrazione (protocollo)
    let service = ServiceProvider.shared.getService()
    service.performAction()
}

// Esempi di polimorfismo con client flessibile
// ServiceProvider.shared.setService(MockService())
// flexibleClientFunction() utilizzerà MockService

Pertanto, l'uso diretto della proprietà statica shared del Singleton nel codice client riduce la flessibilità e ostacola la sostituzione delle implementazioni, che è un aspetto chiave del polimorfismo quando si lavora con diversi tipi di oggetti tramite un'interfaccia comune. La soluzione è lavorare con l'istanza del Singleton tramite un protocollo o una classe base.