Possiamo aggiustare la collaudabilità di Singletons?

-4

È noto che Singletons è anti-pattuglia per diversi motivi:

  1. accoppiamento stretto
  2. singletons sono bugiardi patologici
  3. nessuna testabilità
  4. l'ereditarietà non è disponibile
  5. non puoi programmare interfacce, programmi alle implementazioni

Ma c'è il codice:

class ISingleton
{
protected:
    ISingleton() {}

public:
    virtual ISingleton& getInstance() = 0;
    virtual void doSomething() = 0;
    virtual ~ISingleton(){}
};

class SingletonA : public ISingleton
{
public:
    virtual SingletonA& getInstance() override
    {
        static SingletonA instance;
        return instance;
    }

    virtual void doSomething() override
    {

    }
};

class SingletonB : public ISingleton
{
public:
    virtual SingletonB& getInstance() override
    {
        static SingletonB instance;
        return instance;
    }

    virtual void doSomething() override
    {

    }
};

class DependsOnSingleton
{
private:
    ISingleton& m_singleton;

public:
    DependsOnSingleton(ISingleton& singleton)
        : m_singleton {singleton}
    {

    }

    void use()
    {
        m_singleton.doSomething();
    }
};

Vedi qualche problema nel codice sopra elencato? E assicura completamente che possa essere creata una singola istanza. Potete vedere qui che viene usata l'iniezione diretta delle dipendenze, potrebbe anche essere usata con i contenitori DI. Penso che le persone non capiscano cosa sia Singleton. Mi manca qualcosa?

    
posta Narek 23.09.2016 - 09:08
fonte

2 risposte

7

Do you see any of the problems in the code listed above? And it completely assures that a single instance can be created.

No, assolutamente no.

class SingletonC : public ISingleton
{
public:
    virtual SingletonC& getInstance() override
    {
        return *this;
    }

    virtual void doSomething() override
    {

    }
};

Ora puoi creare tutte le istanze che vuoi. L'intera idea di getInstance non ha nemmeno lontanamente senso quando si tratta di un metodo non statico, poiché per definizione, devi già avere un'istanza per chiamarlo.

Inoltre, il tuo codice non è testabile, poiché le implementazioni di SingletonA e SingletonB non possono essere testate a causa del loro stato mutabile memorizzato staticamente, e non possono accettare interfacce DI-style dal momento che non sono costruite.

    
risposta data 23.09.2016 - 09:16
fonte
2

Poiché il metodo getInstance non è statico, ciò significa che è necessario prima istanziare la classe. Quindi, se vuoi avere un'istanza di B, devi prima creare una "nuova B ()". Non vedo alcun valore di questo. Se fai new A() getInstance() restituirà un'istanza di tipo A

Se vuoi usare i singleton senza i problemi che accompagnano i pattern. Utilizzare le iniezioni (sia in fase di costruzione o utilizzando setter) come fa la primavera.

Hai i vantaggi del singleton con meno svantaggi.

    
risposta data 23.09.2016 - 09:15
fonte