Singleton

**Singleton** (ainokainen) on ohjelmistotekniikassa käytetty suunnittelumalli, jolla varmistetaan että luokasta tehdyllä oliolla on vain yksi instanssi, ja tarjoaa globaalin (ohjelman laajuisen) pääsyn siihen. 

Singleton-mallilla olevia etuja ovat muun muassa:
* hallittu pääsy tietoon (kapselointi)
* rajattu nimiavaruus ja näkyvyys () verrattuna globaaleihin muuttujiin

Mallin toteus riippuu käytetystä ohjelmointikielestä. Eräs C++:ssa käytetty tapa on toteuttaa Singleton-luokka template-mallin avulla.

## Käyttö
Singleton-luokalle tehdään yksityinen (private) konstruktori ja julkinen staattinen luokkametodi (tavallisesti nimetty getInstance()), joka palauttaa yksityiseksi luokkamuuttujaksi tallennetun instanssin. Tämä takaa sen, että uutta oliota ei voida luoda, mutta kyseiseen instanssiin on globaali pääsy.

Singleton instanssin alustaminen voidaan toteuttaa kahdella tavalla: ennen luokan käyttöä (eager initialization, vapaa suomennos: innokas alustus) tai kutsuttaessa ensimmäisen kerran oliota getInstance()-metodilla (lazy initialization, vapaa suomennos: laiska alustus).

### Eager initialization (innokas alustus)
Luokan instanssi luodaan siinä vaiheessa, kun luokka alustetaan - ei siinä vaiheessa, kun sitä käytetään. Tämä voi aiheuttaa tarpeetonta resurssien käyttämistä, jos luokkaa ei käytetä kyseisessä ohjelman ajossa. Voi heikentää suorituskykyä, jos luokka käyttää paljon resursseja. Tämä alustus on kuitenkin säieturvallinen (thread-safe). Ei siis ole mahdollista, että erilliset säikeet saavat omia instanssejaan luokasta.
```java
public class Singleton {
    // Alustetaan singleton-instanssi jo siinä vaiheessa, kun luodaan luokka
    private static final Singleton singleton = new Singleton();
    
    private Singleton() {
        // Yksityinen rakentaja, jotta ohjelmassa ei voida luoda uusia instansseja
    }
    
    // Julkinen luokkametodi, joka palauttaa luodun instanssin
    public static Singleton getInstance() {
        return singleton;
    }
    
    // ... luokalle tarpeellisia metodeja
}
```


### Lazy initialization (laiska alustus)
Luo esiintymän, vasta kun olio kutsutaan ohjelmassa. Tavallisin singletonin esiintymä.  Aiheuttaa ongelmia monisäikeisissä (multi-threaded) järjestelmissä, koska jokainen säie saa oman instanssin. 
```java
public class Singleton {
    private static Singleton singleton = null;
    
    private Singleton() {
        // Yksityinen rakentaja
    }
    
    // Instanssin palauttava luokkametodi, jossa luodaan instanssi, kun sitä kutsutaan
    // ensimmäisen kerran ja palautetaan sama instanssi uudestaan kutsuttaessa
    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
    
    // ... luokalle tarpeellisia metodeja
}
```
Alustusta voidaan kuitenkin muokata säieturvalliseksi tekemällä getInstance()-metodista synkronoitu (synchronized) tai käyttämällä paremman suorituskyvyn mahdollistavaa double-checked locking -keinoa, joka on esitetty alla. Kahdella if-lauseella varmistetaan se, että luokasta on olemassa vain yksi ilmentymä.
```java
public static Singleton getInstance() {
    if (singleton == null) {
        synchronized (Singleton.class) {
            if (singleton == null) {
                singleton = new Singleton();
            }
        }
    }
    return singleton;
}
```


## Kritiikki
Kriitikot eivät pidä singletonia suunnittelumallina, vaan ns. epäsuunnittelumallina. Syitä tähän on arveltu olevan mallin yksinkertaisuus ja väärinkäyttö osaamattomissa käsissä. Singletonien ajatellaan lisäävän moduulien keskinäistä riippuvuutta ja siten vaikeuttavan yksikkötestejä.

## Lähteet
* 

### Viitteet