Kihagyás

Singleton (Egyke)

Kategória: Létrehozási minta (Creational Pattern)

Lényege és célja

A Singleton minta célja, hogy garantálja: egy osztálynak egyetlen példánya létezik a teljes alkalmazásban, és ehhez a példányhoz egy globális hozzáférési pontot biztosít.

Gyakran használjuk olyan erőforrásoknál, amelyekből rendszerszinten csak egyre van szükség, vagy amelyek megosztása kritikus (pl. konfigurációs fájlok beolvasása, naplózó osztályok, vagy hardver-erőforrások kezelése).

A Singleton "szentháromsága" (Hogyan ismerjük fel?):

  1. Privát konstruktor: Megakadályozza, hogy külső kód a new kulcsszóval új példányt hozzon létre.
  2. Statikus mező: Ebben az osztályban tároljuk el az egyetlen létező példányt.
  3. Statikus getInstance() metódus: Ez az egyetlen út a példány eléréséhez. Ha még nem létezik, létrehozza, ha már létezik, visszadja a meglévőt.

Mikor használjuk?

  • Amikor egy osztályból pontosan egy példányra van szükség az egész rendszerben.
  • Amikor szigorúan kontrollálni kell a hozzáférést egy megosztott erőforráshoz.
  • Amikor a globális változók használatát szeretnénk elkerülni, de szükség van egy közös elérési pontra.

Figyelem: A Singleton tesztelése (Unit Testing) nehézkes lehet, és néha "anti-pattern"-nek tekintik, ha túlzottan sok állapotot tárolunk benne, mert elrejti az osztályok közötti függőségeket.

Miért Java enum

Java-ban a Singleton gyakran enum-ként van megvalósítva, mert a JVM garantálja az egyetlen példány létrehozását. Az enum példányok az osztálybetöltés (class loading) során jönnek létre, ami a JVM specifikáció szerint szálbiztos, ezért nincs szükség külön szinkronizációra.

Fontos azonban, hogy ez csak a példány létrehozására igaz: ha az enum belső állapota módosítható (pl. mezőket változtatsz több szálról), akkor arról már neked kell gondoskodni (pl. synchronized, volatile, vagy egyéb konkurens megoldások).

Az enum további előnye, hogy védett a szerializációval szemben: deszerializáláskor a JVM nem hoz létre új példányt, hanem automatikusan a már létező enum konstansra hivatkozik vissza. Emellett reflektív úton sem példányosítható újra, így ezek a klasszikus Singleton-törési lehetőségek ki vannak zárva.

Mermaid Diagram

A diagram az osztály önmagára mutató kapcsolatát ábrázolja, ahol a statikus metódus és mező felel a példány kezeléséért.

classDiagram
    class Singleton {
        -instance: Singleton$
        -Singleton()
        +getInstance()$ Singleton
        +doSomething() void
    }
    note for Singleton "A private konstruktor miatt\nkívülről nem hívható a 'new'"
    Singleton --> Singleton : "tárolja az egyetlen példányt"

Forráskód

package creational.singleton;

enum AppConfig {
    INSTANCE;

    public String getDBUrl() {
        return "localhost:1234";
    }
}


class Main {
    static void main() {
        System.out.println(AppConfig.INSTANCE.getDBUrl());
    }
}