Differenza tra classe statica e modello singleton?


1769

Che differenza reale (cioè pratica) esiste tra una classe statica e un modello singleton?

Entrambi possono essere invocati senza istanza, entrambi forniscono solo una "Istanza" e nessuno dei due è thread-safe. C'è qualche altra differenza?


4
A seconda dell'implementazione del linguaggio e dei modelli di utilizzo, un Singleton potrebbe essere meno efficiente a causa del sovraccarico di chiamare il getInstance()metodo ogni volta che si desidera utilizzarlo (anche se probabilmente nella maggior parte dei casi non importa ).
troppo php,

5
Ci sono già molte risposte. In realtà è un singletonoggetto in cui i staticmetodi sono solo funzioni, un'entità non OO.
fastcodejava,


4
C'è una differenza quando si desidera consentire a terzi di fornire l'implementazione della classe. In questo caso di solito è necessario anche uno schema Factory. Vedi agiletribe.wordpress.com/2013/10/08/…
AgilePro

IMO questa risposta la riassume molto bene stackoverflow.com/questions/14097656/…
Dave,

Risposte:


1251

Cosa ti fa dire che un metodo singleton o statico non è thread-safe? Normalmente entrambi dovrebbero essere implementati per essere thread-safe.

La grande differenza tra un singleton e un mucchio di metodi statici è che i singleton possono implementare interfacce (o derivare da utili classi base, anche se è meno comune, nella mia esperienza), quindi puoi passare il singleton come se fosse "solo un altro " implementazione.


29
Bene, se lo preferisci, nessuno dei due è intrinsecamente sicuro per i thread, devi renderli sicuri per i thread, entrambi, quindi nessuna differenza lì.
Jorge Córdoba,

119
Puoi fare un esempio di qualcosa che è intrinsecamente sicuro per i thread, diverso dai tipi immutabili?
Jon Skeet,

26
Per Skeet: le persone che affermano che singleton non è sicuro per i thread significano che un singleton è condiviso tra thread inutilmente per tutto il tempo, mentre gli oggetti stack vengono condivisi quando ne hai bisogno, il che significa che non è necessario eseguire una sincronizzazione non necessaria.

45
@Geek: Immagina che il singleton implementi un'interfaccia Fooe hai un metodo che prende Fooun parametro. Con tale impostazione, i chiamanti possono scegliere di utilizzare il singleton come implementazione oppure possono utilizzare un'implementazione diversa. Il metodo è disaccoppiato dal singleton. Confrontalo con la situazione in cui la classe ha solo metodi statici: ogni parte di codice che vuole chiamare quei metodi è strettamente accoppiata alla classe, perché deve specificare quale classe contiene i metodi statici.
Jon Skeet,

10
@AmirBareket: Tuttavia, non è un singleton secondo il modello di progettazione singleton - se la classe stessa consente di creare più istanze, non è un IMO singleton, indipendentemente da ciò che fa la fabbrica.
Jon Skeet,

476

La vera risposta è di Jon Skeet, su un altro forum qui .

Un singleton consente l'accesso a una singola istanza creata: tale istanza (o meglio, un riferimento a tale istanza) può essere passata come parametro ad altri metodi e trattata come un oggetto normale.

Una classe statica consente solo metodi statici.


64
Perché dovresti passare un Singleton come parametro, tuttavia, se riesci ad accedere alla stessa istanza da qualsiasi luogo chiamando il metodo statico getInstance ()?
Henrique Ordine,

23
@HenriqueOrdine Quindi può adattarsi al codice esistente e fornire un'interfaccia?

6
@HenriqueOrdine Stanno parlando della classe statica, non di una classe con metodi statici. La classe statica non può essere istanziata. Tuttavia, se si passa un'istanza di una classe (non statica) che contiene metodi statici, non è possibile chiamare metodi statici su un'istanza.
Goran,

3
Che cos'è una classe statica? Almeno in Java, non esiste nulla del genere.
Henrique Ordine,

16
@Goran Ero inizialmente molto confuso dalle tue parole. Hai detto "non puoi chiamare metodi statici su un'istanza". Ho letto che "se hai un riferimento a un oggetto istanziato, non puoi chiamare alcun metodo statico che potrebbe avere". Questo è ovviamente errato. Dopo averlo letto di nuovo alcune volte, penso che tu abbia inteso "dall'interno dei metodi statici non puoi accedere ad oggetti non statici nella classe", il che è corretto. Vuoi chiarire che per chiunque sia nuovo a questi concetti che incontra questa risposta e legge i tuoi commenti.
Andrew Steitz,

359
  1. Gli oggetti Singleton sono archiviati in Heap , ma gli oggetti statici sono memorizzati in pila .
  2. Possiamo clonare (se il progettista non lo ha impedito) l'oggetto singleton, ma non possiamo clonare l'oggetto di classe statica.
  3. Le classi Singleton seguono OOP (principi orientati agli oggetti), le classi statiche no.
  4. Possiamo implementare un interfacecon una classe Singleton, ma i metodi statici di una classe (o ad esempio un C # static class) no.

100
La seconda affermazione è sbagliata. Non possiamo clonare oggetti Singleton. L'implementazione di Singleton deve rifiutare questo. Se riesci davvero a clonare Singleton, non è Singleton.
Alexander Yancharuk,

19
Questa è una risposta non corretta per Java: né lo singleton né lo statico usano lo stack.
AgilePro

72
# 1 non è importante. # 2 descrive un'implementazione difettosa. # 3 è completamente ingiustificabile.
Casey,

31
Come si può archiviare l'oggetto statico nello stack? Il nuovo frame dello stack viene creato quando si richiama un metodo, memorizza le variabili locali del metodo, questo frame dello stack viene rimosso quando il metodo ritorna e tali variabili locali vengono perse. Lo stack è veloce, ma non è adatto per memorizzare oggetti statici.
mike_m,

23
Non riesco a capire il numero di voti su questo. 1) Perché Singleton dovrebbe essere archiviato in pila? In linguaggi gestiti come C # o Java i dati sono archiviati in un heap gestito, ad eccezione delle variabili / parametri del metodo locale. 2) Se riesci a clonarlo, non è un singleton correttamente implementato. 3) Singleton è noto come anti-pattern OOP; cioè qualcosa che dovresti evitare, se possibile. 4) Questa è l'unica cosa corretta.
Groo,

152

Il modello Singleton presenta numerosi vantaggi rispetto alle classi statiche. Innanzitutto, un singleton può estendere le classi e implementare le interfacce, mentre una classe statica non può (può estendere le classi, ma non eredita i loro membri di istanza). Un singleton può essere inizializzato pigramente o in modo asincrono mentre una classe statica viene generalmente inizializzata quando viene caricata per la prima volta, portando a potenziali problemi con il caricatore di classi. Tuttavia, il vantaggio più importante, tuttavia, è che i singleton possono essere gestiti polimorficamente senza costringere i loro utenti ad assumere che esista solo un'istanza.


10
+1 per punti buoni e pragmatici. Il modello Singleton è abusato in generale, ma ci sono alcune situazioni in cui si adatta. Vedi anche: agiletribe.wordpress.com/2013/10/08/…
AgilePro

3
Hai ragione sul vantaggio di essere polimorfico. Questo è il punto più importante
Ahmad,

La classe statica nidificata può implementare l'interfaccia. Prova a codificarlo, funzionerà. Potrei compilare il codice senza errori.
nanosoft,

75

staticle classi non sono per tutto ciò che necessita di stato. È utile per mettere insieme un sacco di funzioni, ovvero Math(o Utilsnei progetti). Quindi il nome della classe ci dà solo un indizio su dove possiamo trovare le funzioni e nient'altro.

Singletonè il mio modello preferito e lo uso per gestire qualcosa in un unico punto. È più flessibile delle staticclassi e può mantenere il suo stato. Può implementare interfacce, ereditare da altre classi e consentire l'ereditarietà.

La mia regola per scegliere tra statice singleton:

Se ci sono un sacco di funzioni che dovrebbero essere tenute insieme, allora staticè la scelta. Qualsiasi altra cosa che necessita di un singolo accesso ad alcune risorse, potrebbe essere implementata come a singleton.


16
Perché le classi statiche non dovrebbero fare nulla per salvare lo stato?
Trisped

12
@Trisped: non hai né un controllo preciso sull'inizializzazione né sulla finalizzazione.
Xaqron,

7
mi hai perso in "Singleton è il mio modello preferito". Singleton è un angolo così acuto che dovrebbe essere considerato un anti-pattern oltre che un pattern. Le classi possono anche avere stati statici, che sono anche ad accesso singolo, se qualcosa di statico è più "single access" rispetto ai singoli, perché la maggior parte delle implementazioni singleton sono interrotte, ad es. puoi clonare il singleton, mentre static è benedetto dalla definizione di essere unico.
PoweredByRice

1
Cosa significa mantenere lo stato? Che cos'è lo stato?
Kyle Delaney,

2
@KyleDelaney: Stateè semplicemente la combinazione di diverse proprietà di un oggetto che di solito cambiano nel tempo. Puoi Google per la definizione formale.
Xaqron,

65

Classe statica: -

  1. Non è possibile creare l'istanza di classe statica.

  2. Caricato automaticamente da Common Language Runtime (CLR) di .NET Framework quando viene caricato il programma o lo spazio dei nomi contenente la classe.

  3. La classe statica non può avere un costruttore.

  4. Non è possibile passare la classe statica al metodo.

  5. Non possiamo ereditare la classe statica in un'altra classe statica in C #.

  6. Una classe con tutti i metodi statici.

  7. Migliori prestazioni (i metodi statici sono collegati al momento della compilazione)

Singleton:-

  1. È possibile creare un'istanza dell'oggetto e riutilizzarlo.

  2. L'istanza Singleton viene creata per la prima volta quando l'utente ha richiesto.

  3. La classe Singleton può avere un costruttore.

  4. È possibile creare l'oggetto della classe singleton e passarlo al metodo.

  5. La classe Singleton non dice alcuna restrizione di ereditarietà.

  6. Possiamo disporre gli oggetti di una classe singleton ma non di una classe statica.

  7. I metodi possono essere ignorati.

  8. Può essere lazy caricato quando necessario (le classi statiche vengono sempre caricate).

  9. Siamo in grado di implementare l'interfaccia (la classe statica non può implementare l'interfaccia).


13
Le classi statiche hanno costruttori: msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
Tomer Arazy

2
Sì, statico può avere un costruttore interno a quella classe. Questo viene invocato quando viene chiamato qualsiasi metodo statico nella classe.
rahulmr,

Per singleton in fase di compilazione, viene archiviato nella memoria HEAP ma se viene istanziato una volta viene archiviato in STACK?
Luminous_Dev,

@Luminous_Dev No. Qualsiasi istanza singleton è un'istanza di oggetto alla fine della giornata. Verrà memorizzato sull'heap senza dubbio.
RBT

1
@rahulmr Importante distinzione: il costruttore viene anche invocato prima della creazione della prima istanza (solo AKA).
CoolOppo

53

Una classe statica è quella che ha solo metodi statici, per i quali una parola migliore sarebbe "funzioni". Lo stile di progettazione incarnato in una classe statica è puramente procedurale.

Singleton, d'altra parte, è un modello specifico per il design OO. È un'istanza di un oggetto (con tutte le possibilità inerenti a ciò, come il polimorfismo), con una procedura di creazione che assicura che esista solo un'istanza di quel particolare ruolo per tutta la sua vita.


1
il polimorfismo non entra in gioco con i

32
Quindi pensi. Penso diversamente. ;) Ad esempio, immagina una fabbrica singleton che restituisca un'interfaccia. Sai che stai ricevendo un ISingleton (ed è lo stesso per sempre) ma non necessariamente quale implementazione.
Morendil,

La classe statica nidificata può avere anche metodi di istanza, non è limitata solo ai metodi statici. Codificala e puoi vedere.
nanosoft,

Nelle lingue con un modello a oggetti più gradevole (ad es. Ruby), anche le classi sono oggetti. L'aspetto "puramente procedurale" di una classe statica è una restrizione arbitraria imposta dal linguaggio.
Max

36

Nel modello singleton puoi creare il singleton come istanza di un tipo derivato, non puoi farlo con una classe statica.

Esempio rapido:

if( useD3D )
    IRenderer::instance = new D3DRenderer
else
    IRenderer::instance = new OpenGLRenderer

39
Non è proprio un modello singleton, mi sembra più una fabbrica.
vava,

10
Non proprio, la differenza fondamentale tra i due è che Singleton "memorizzerà nella cache" il suo singolo oggetto e continuerà a restituire (un riferimento a) lo stesso. Il modello Factory creerà nuove istanze.
Mistico

12
Quindi è proxy-singleton :)
vava

3
Hmm, conosco questa varietà di Singleton come MonoState.
Huppie,

l'esempio è il modello di fabbrica
Rajavel D,

26

Per espandere la risposta di Jon Skeet

La grande differenza tra un singleton e un mucchio di metodi statici è che i singleton possono implementare interfacce (o derivare da utili classi di base, anche se questo è meno comune IME), quindi puoi passare intorno al singleton come se fosse "solo un'altra" implementazione.

I singleton sono più facili da lavorare quando l'unità verifica una classe. Ovunque passi i singleton come parametro (costruttori, setter o metodi) puoi invece sostituire una versione derisa o mozzata del singleton.


Non penso che tu possa prendere direttamente in giro un singleton. Non dovresti dichiarare un'interfaccia implementata sia dalla classe singleton che da quella finta?
Ellen Spertus,

@espertus Perché non riesci a deridere il tuo singleton? Esempio usando mockito MySingleton mockOfMySingleton = mock(MySingleton.class).
Mike Rylander,

hai ragione, puoi deriderlo con strumenti come il mockito che usano la riflessione. Intendevo dire che non puoi deriderlo direttamente subclassandolo e sovrascrivendone i metodi.
Ellen Spertus,

@espertus Perché no? Quando si crea un'istanza dell'oggetto che si sta testando, è possibile sostituire l'implementazione della sottoclasse del singleton ovunque si sarebbe utilizzato l'originale. Esempio:new ClazzToTest(mockSingleton);
Mike Rylander,

Non ho usato Mockito, ma come puoi sottoclassare una classe che ha un costruttore privato, come nel caso dei singoli, se non usando la riflessione? Discussioni correlate: stackoverflow.com/questions/2302179/mocking-a-singleton-class stackoverflow.com/questions/15939023/…
Ellen Spertus,

23

Ecco un buon articolo: http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

Classi statiche

  • una classe con tutti i metodi statici .
  • prestazioni migliori (i metodi statici sono collegati al momento della compilazione)
  • non può ignorare i metodi, ma può usare il metodo nascosto. ( Qual è il metodo nascosto in Java? Anche la spiegazione JavaDoc è confusa )

    public class Animal {
        public static void foo() {
            System.out.println("Animal");
        }
    }
    
    public class Cat extends Animal {
        public static void foo() {  // hides Animal.foo()
            System.out.println("Cat");
        }
    }
    

Singleton

In sintesi, userei solo le classi statiche per contenere i metodi util e usare Singleton per tutto il resto.


Le modifiche


4
Non so di Java, ma in .Net, i tuoi ultimi due punti non sono corretti. Le classi statiche possono fare riferimento a proprietà e campi statici, quindi allo stato sono uguali. E sono pigri - il costruttore statico viene eseguito quando: 1) Viene creata un'istanza della classe. 2) Si fa riferimento a qualsiasi membro statico della classe. 1 non si applica, il che lascia 2. Quindi, una classe statica non viene caricata fino alla prima volta che viene utilizzata.
jmoreno,

1
Per la classe statica, sebbene non sia possibile sovrascrivere il metodo statico, è possibile nascondere il metodo statico dal suo genitore.
Max Peng

se Animal animal = new Cat();allora animal.foo();cosa succede?
Luminous_Dev,

La classe statica @jmoreno non viene caricata fino al primo utilizzo? Credo che sia archiviato nella memoria dello stack al momento della compilazione. Ed è immediatamente accessibile .. non è vero?
Luminous_Dev,

@Luminous_Dev: almeno per .net, una classe statica ha un costruttore che viene eseguito al primo accesso, quindi non è immediatamente accessibile. Il costruttore statico potrebbe in teoria impiegare una quantità illimitata di tempo. Dove (o qualsiasi altra classe è memorizzata) è un dettaglio di implementazione, che non è realmente rilevante per questa domanda.
jmoreno,

22

Un altro vantaggio di un singleton è che può essere facilmente serializzato, il che potrebbe essere necessario se è necessario salvarne lo stato su disco o inviarlo da qualche parte da remoto.


19

Non sono un grande teorico OO, ma da quello che so, penso che l'unica caratteristica OO che manca alle classi statiche rispetto ai Singleton sia il polimorfismo. Ma se non ne hai bisogno, con una classe statica puoi ovviamente avere ereditarietà (non sono sicuro dell'implementazione dell'interfaccia) e incapsulamento di dati e funzioni.

Il commento di Morendil, "Lo stile di progettazione incarnato in una classe statica è puramente procedurale" Potrei sbagliarmi, ma non sono d'accordo. Nei metodi statici è possibile accedere ai membri statici, che sarebbero esattamente gli stessi dei metodi singleton che accedono ai loro membri a istanza singola.

modifica:
In realtà sto pensando ora che un'altra differenza è che una classe statica è istanziata all'avvio del programma * e vive per tutta la durata del programma, mentre un singleton è istanziato esplicitamente ad un certo punto e può anche essere distrutto.

* o potrebbe essere istanziato al primo utilizzo, a seconda della lingua, credo.


15
Sì, tutti gli altri sembrano ignorare il fatto che una classe con metodi statici può avere anche campi statici privati ​​che può ancora utilizzare per mantenere lo stato (ed esporne alcuni al codice client tramite setter / getter statici pubblici).
user289463

17

Per illustrare il punto di Jon ciò che viene mostrato di seguito non può essere fatto se Logger fosse una classe statica. La classe SomeClassprevede che un'istanza di ILoggerimplementazione venga passata al suo costruttore.

La classe Singleton è importante affinché sia ​​possibile l'iniezione di dipendenza.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var someClass = new SomeClass(Logger.GetLogger());
        }


    }

    public class SomeClass 
    {
        public SomeClass(ILogger MyLogger)
        {

        }
    }

    public class Logger : ILogger
    {
        private static Logger _logger;
        private Logger() { }

        public static Logger GetLogger()
        {
            if (_logger==null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void Log()
        {

        }

    }


    public interface ILogger
    {
         void Log();
    }
}

13

Bene, un singleton è solo una classe normale che viene istanziata ma solo una volta e indirettamente dal codice client. La classe statica non è istanziata. Per quanto ne so i metodi statici (la classe statica deve avere metodi statici) sono più veloci di quelli non statici.

Modifica:
descrizione della regola delle prestazioni di FxCop: "I metodi che non accedono ai dati dell'istanza o ai metodi dell'istanza di chiamata possono essere contrassegnati come statici (condivisi in VB). Successivamente, il compilatore emetterà siti di chiamata non virtuali a questi membri che impediranno un verifica in fase di esecuzione per ogni chiamata che assicuri che il puntatore dell'oggetto corrente sia non nullo. Ciò può comportare un guadagno misurabile delle prestazioni per il codice sensibile alle prestazioni. In alcuni casi, il mancato accesso all'istanza dell'oggetto corrente rappresenta un problema di correttezza. "
In realtà non so se questo si applica anche ai metodi statici nelle classi statiche.


11

Le istanze di Singleton sono istanziate, è solo un'istanza mai istanziata, quindi il singolo in Singleton.

Una classe statica non può essere istanziata da qualcosa di diverso da se stesso.


La classe statica può essere molto istanziata in Java. Leggi docs.oracle.com/javase/tutorial/java/javaOO/nested.html. Fare riferimento anche la mia risposta stackoverflow.com/a/37114702/1406510
Nanosoft

8

Le principali differenze sono:

  • Singleton ha un'istanza / oggetto mentre la classe statica è un gruppo di metodi statici
  • Singleton può essere esteso, ad esempio attraverso un'interfaccia, mentre la classe statica non può essere.
  • Singleton può essere ereditato, il che supporta i principi di apertura / chiusura nei principi SOLID, d'altra parte, la classe statica non può essere ereditata e dobbiamo apportare modifiche in sé.
  • L'oggetto Singleton può essere passato ai metodi mentre la classe statica in quanto non ha istanza non può essere passata come parametri

7

Singleton è un approccio migliore dal punto di vista dei test. A differenza delle classi statiche, singleton potrebbe implementare interfacce ed è possibile utilizzare l'istanza finta e iniettarle.

Nell'esempio che segue illustrerò questo. Supponiamo di avere un metodo isGoodPrice () che utilizza un metodo getPrice () e di implementare getPrice () come metodo in un singleton.

singleton che fornisce funzionalità getPrice:

public class SupportedVersionSingelton {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        // calculate price logic here
        return 0;
    }
}

Uso di getPrice:

public class Advisor {

    public boolean isGoodDeal(){

        boolean isGoodDeal = false;
        ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
        int price = supportedVersion.getPrice();

        // logic to determine if price is a good deal.
        if(price < 5){
            isGoodDeal = true;
        }

        return isGoodDeal;
    }
}


In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it. 



  public interface ICalculator {
        int getPrice();
    }

Implementazione finale di Singleton:

public class SupportedVersionSingelton implements ICalculator {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        return 0;
    }

    // for testing purpose
    public static void setInstance(ICalculator mockObject){
        if(instance != null ){
instance = mockObject;
    }

classe di prova:

public class TestCalculation {

    class SupportedVersionDouble implements ICalculator{
        @Override
        public int getPrice() { 
            return 1;
        }   
    }
    @Before
    public void setUp() throws Exception {
        ICalculator supportedVersionDouble = new SupportedVersionDouble();
        SupportedVersionSingelton.setInstance(supportedVersionDouble);

    }

    @Test
    public void test() {
          Advisor advidor = new Advisor();
          boolean isGoodDeal = advidor.isGoodDeal();
          Assert.assertEquals(isGoodDeal, true);

    }

}

Nel caso in cui prendiamo l'alternativa dell'uso del metodo statico per l'implementazione di getPrice (), è stato difficile simulare getPrice (). Potresti deridere l'elettricità statica con power mock, ma non tutti i prodotti potrebbero usarlo.


1
Questo non è ora thread-safe, e generalmente sgradevole in termini di accesso alla implementazione dell'interfaccia. Certo, avere un'interfaccia è bello per la testabilità - ma allora perché preoccuparsi di un singleton? Evita semplicemente di avere un singleton; avere una classe che lo implementa per scopi di produzione, una implementazione per scopi di test e iniettare l'istanza giusta a seconda di cosa stai facendo. Non è necessario abbinare affatto il singleton ai suoi chiamanti.
Jon Skeet,

Grazie per il feedback. è molto semplice renderlo sicuro per i thread. inoltre, utilizzo singleton a scopo di memorizzazione nella cache.
Amir Bareket,

1
Sì, anche se con inutili spese generali. Ancora una volta, è più semplice non usare un singleton.
Jon Skeet,

6

Sono d'accordo con questa definizione:

La parola " singolo " indica un singolo oggetto nel ciclo di vita dell'applicazione, quindi l'ambito è a livello di applicazione.

Lo statico non ha alcun puntatore all'oggetto, quindi l'ambito è a livello di dominio app.

Inoltre, entrambi dovrebbero essere implementati per essere thread-safe.

Puoi trovare interessanti altre differenze su: Singleton Pattern Versus Static Class


5

Una notevole differenza è la diversa istanza fornita con i Singleton.

Con le classi statiche, viene creato dal CLR e non abbiamo il controllo su di esso. con i singoli, l'oggetto viene istanziato nella prima istanza a cui si tenta di accedere.


4

In molti casi, questi due non hanno alcuna differenza pratica, soprattutto se l'istanza singleton non cambia mai o cambia molto lentamente, ad esempio mantenendo le configurazioni.

Direi che la differenza più grande è che un singleton è ancora un normale Java Bean in contrapposizione a una classe Java solo statica specializzata. E per questo motivo, un singleton è accettato in molte altre situazioni; è in effetti la strategia di istanza predefinita di Spring Framework. Il consumatore può o meno sapere che è un singleton che viene passato in giro, lo tratta semplicemente come un normale bean Java. Se invece i requisiti cambiano e un singleton deve invece diventare un prototipo, come spesso vediamo in primavera, può essere fatto senza soluzione di continuità senza una linea di modifica del codice per il consumatore.

Qualcun altro ha menzionato in precedenza che una classe statica dovrebbe essere puramente procedurale, ad esempio java.lang.Math. Nella mia mente, una tale classe non dovrebbe mai essere passata in giro e non dovrebbero mai contenere qualcosa di diverso dal finale statico come attributi. Per tutto il resto, usa un singleton poiché è molto più flessibile e più facile da mantenere.


4

Abbiamo il nostro framework DB che effettua connessioni al back-end. Per evitare letture sporche su più utenti, abbiamo utilizzato il modello singleton per garantire la disponibilità di una singola istanza in qualsiasi momento.

In c # una classe statica non può implementare un'interfaccia. Quando una singola classe di istanza deve implementare un'interfaccia per contratti aziendali o scopi IoC, è qui che utilizzo il modello Singleton senza una classe statica

Singleton fornisce un modo per mantenere lo stato in scenari senza stato

Spero che ti aiuti ..


3
  1. Caricamento pigro
  2. Supporto di interfacce, in modo che sia possibile fornire un'implementazione separata
  3. Capacità di restituire il tipo derivato (come una combinazione di lazyloading e implementazione dell'interfaccia)

La classe statica nidificata può implementare moltissimo l'interfaccia in Java. Il tuo secondo punto è sbagliato.
nanosoft,

3

un. Serializzazione: i membri statici appartengono alla classe e quindi non possono essere serializzati.

b. Sebbene abbiamo reso privato il costruttore, le variabili dei membri statici verranno comunque trasferite nella sottoclasse.

c. Non è possibile eseguire l'inizializzazione lazy poiché tutto verrà caricato solo durante il caricamento della classe.


3

Dal punto di vista del client, il comportamento statico è noto al client ma il comportamento Singleton può essere completato nascosto da un client. Il cliente potrebbe non sapere mai che c'è solo una singola istanza con cui gioca ancora e ancora.


3

Ho letto quanto segue e penso che abbia anche senso:

Prendersi cura degli affari

Ricorda, una delle regole OO più importanti è che un oggetto è responsabile di se stesso. Ciò significa che i problemi relativi al ciclo di vita di una classe devono essere gestiti nella classe, non delegati a costrutti di linguaggio come statici e così via.

dal libro Processo di pensiero orientato agli oggetti 4a ed.


Non sarei d'accordo, dato che questo aggiunge davvero una responsabilità alla classe, il che (supponendo che faccia qualsiasi cosa) significa che ora viola il Principio della singola responsabilità.
fabbro

3

In un articolo che ho scritto ho descritto il mio punto di vista sul perché il singleton è molto meglio di una classe statica:

  1. La classe statica non è in realtà una classe canonica, è uno spazio dei nomi con funzioni e variabili
  2. L'uso della classe statica non è una buona pratica a causa della violazione dei principi di programmazione orientata agli oggetti
  3. La classe statica non può essere passata come parametro per altri
  4. La classe statica non è adatta all'inizializzazione "pigra"
  5. L'inizializzazione e l'utilizzo della classe statica sono sempre difficili da tracciare
  6. L'implementazione della gestione dei thread è difficile

Vorrei rispolverarlo per la grammatica inglese, ma per il resto, è una lettura interessante :)
Noctis

3
  1. Possiamo creare l'oggetto della classe singleton e passarlo al metodo.

  2. La classe Singleton non ha alcuna restrizione di eredità.

  3. Non possiamo disporre gli oggetti di una classe statica ma possiamo singleton class.


A che serve passare un singleton in un metodo se ce n'è sempre solo uno e quello ha sempre un riferimento statico?
Aaron Franke,

3

Distinzione dalla classe statica

JDK ha esempi di singleton e statici, da un lato java.lang.Mathè una classe finale con metodi statici, dall'altro java.lang.Runtimeè una classe singleton.

Vantaggi di singleton

  • Se la necessità di mantenere lo stato rispetto al modello singleton è una scelta migliore rispetto alla classe statica, poiché il mantenimento dello stato nella classe statica porta a bug, specialmente in ambiente concorrente, che potrebbero portare a condizioni di competizione senza un'adeguata modifica parallela della sincronizzazione da parte di più thread.

  • La classe Singleton può essere caricata in modo pigro se è un oggetto pesante, ma la classe statica non ha tali vantaggi e sempre caricata avidamente.

  • Con singleton, puoi utilizzare l'ereditarietà e il polimorfismo per estendere una classe di base, implementare un'interfaccia e fornire implementazioni diverse.

  • Poiché i metodi statici in Java non possono essere sovrascritti, portano alla mancanza di flessibilità. D'altra parte, è possibile ignorare i metodi definiti nella classe singleton estendendolo.

Svantaggi della classe statica

  • Scrivere unit test per singleton è più semplice della classe statica, perché è possibile passare un oggetto simulato ogni volta che si prevede che singleton.

Vantaggi della classe statica

  • La classe statica offre prestazioni migliori rispetto a singleton, poiché i metodi statici sono collegati al momento della compilazione.

Esistono diverse realizzazioni del modello singleton ognuna con vantaggi e svantaggi.

  • Desideroso caricamento di singleton
  • Singleton di blocco con doppio controllo
  • Idioma del titolare di inizializzazione su richiesta
  • Il singleton basato sull'enum

Una descrizione dettagliata di ognuno di essi è troppo dettagliata, quindi ho messo un link a un buon articolo - Tutto quello che vuoi sapere su Singleton


2

Esiste un'enorme differenza tra una singola istanza di classe statica (ovvero una singola istanza di una classe, che risulta essere una variabile statica o globale) e un singolo puntatore statico a un'istanza della classe sull'heap:

Quando l'applicazione viene chiusa, verrà chiamato il distruttore dell'istanza della classe statica. Ciò significa che se hai usato quell'istanza statica come singleton, il singleton ha smesso di funzionare correttamente. Se è ancora in esecuzione codice che utilizza quel singleton, ad esempio in un thread diverso, è probabile che il codice si blocchi.


1
Quindi, se l'applicazione esce, Singleton rimarrà ancora in memoria?
nanosoft,

Penso che intendi quando esce il tuo thread attuale, non l'applicazione, giusto? Se l'applicazione viene chiusa, non è possibile che un altro thread ne utilizzi qualcosa.
Tom Brito,

2

La differenza nella mia testa è l'implementazione della programmazione orientata agli oggetti (Singleton / Prototype) o della programmazione funzionale (Static).

Siamo troppo concentrati sul numero di oggetti creati dal modello singleton quando ciò su cui dovremmo concentrarci è che alla fine teniamo un oggetto. Come altri hanno già detto, può essere esteso, passato come parametro ma, soprattutto, è pieno di stato.

D'altra parte, statico viene utilizzato per implementare la programmazione funzionale. I membri statici appartengono a una classe. Sono apolidi.

A proposito, sapevi che puoi creare classi statiche singleton :)


Qual è il punto di passare un singleton come parametro poiché ha sempre un riferimento statico sulla classe?
Aaron Franke,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.