Sobes.tech
Middle+

Como é que o uso do padrão Singleton pode violar os princípios de polimorfismo?

sobes.tech IA

Resposta da IA

O Singleton limita a criação de instâncias de uma classe a um único objeto. No entanto, o polimorfismo implica a capacidade de trabalhar com objetos de diferentes classes através de uma interface comum ou classe base.

A violação ocorre quando o código cliente está rigidamente ligado a uma classe Singleton específica, em vez de trabalhar com uma abstração (protocolo ou classe base). Nesse caso, não é possível substituir por outro objeto alternativo que implemente a mesma funcionalidade, pois o cliente espera exatamente uma instância de Singleton.

// Uso incorreto - o cliente depende diretamente de ConcreteSingleton
class ConcreteSingleton {
    static let shared = ConcreteSingleton()
    private init() {}

    func performAction() {
        print("Executando ação do ConcreteSingleton")
    }
}

// Cliente
func clientFunction() {
    // Dependência rígida de ConcreteSingleton
    ConcreteSingleton.shared.performAction()
}

// Uso correto - o cliente depende de um protocolo
protocol Service {
    func performAction()
}

class RealService: Service {
    func performAction() {
        print("Executando ação do RealService")
    }
}

class MockService: Service {
    func performAction() {
        print("Executando ação do MockService")
    }
}

// Singleton para fornecer implementação através de um protocolo (opcional, pode usar 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
    }
}

// Cliente
func flexibleClientFunction() {
    // Trabalhando através da abstração (protocolo)
    let service = ServiceProvider.shared.getService()
    service.performAction()
}

// Exemplos de polimorfismo com cliente flexível
// ServiceProvider.shared.setService(MockService())
// flexibleClientFunction() usará MockService

Assim, o uso direto da propriedade estática shared do Singleton no código cliente reduz a flexibilidade e dificulta a substituição de implementações, o que é um aspecto chave do polimorfismo ao trabalhar com diferentes tipos de objetos através de uma interface comum. A solução é trabalhar com a instância do Singleton através de um protocolo ou classe base.