Singleton (Singelton)
Introduktion
Singleton är ett skapande mönster som säkerställer att en klass endast har en instans och tillhandahåller en global åtkomstpunkt till den.
Problem
Singleton-mönstret löser två problem samtidigt:
- En enda instans — Viss kod kräver exakt en instans av en klass, t.ex. en databasanslutning eller ett konfigurationsobjekt. Skapar du flera instanser riskerar du inkonsekvent data och onödig resursåtgång.
- Global åtkomst — Objektet ska vara åtkomligt från var som helst i programmet, men skyddat från att skrivas över av misstag.
Lösning
- Privat konstruktor — Förhindrar att andra klasser skapar instanser med
new. - Statisk åtkomstmetod — Skapar instansen vid första anropet och returnerar den cachade instansen vid alla efterföljande anrop.
När ska Singleton användas?
- När en klass i ditt program bara ska ha en enda instans för alla klienter.
- T.ex. delad databasanslutning, logg-system, konfigurationshanterare.
Struktur
| Del | Beskrivning |
|---|---|
| Privat konstruktor | Hindrar direkt instansiering. |
| Statiskt privat fält | Lagrar den enda instansen. |
Statisk getInstance() | Skapar (lazy) eller returnerar den befintliga instansen. |
Exempel — Databasanslutning (TypeScript)
Scenariot: En databasklass som garanterar att bara en anslutning skapas i hela applikationen.
class Database {
private static instance: Database | null = null;
private connectionString: string;
// Privat konstruktor — ingen kan anropa new Database()
private constructor(connectionString: string) {
this.connectionString = connectionString;
console.log(`Databas initierad: ${connectionString}`);
}
// Statisk åtkomstmetod
static getInstance(connectionString: string): Database {
if (!Database.instance) {
Database.instance = new Database(connectionString);
}
return Database.instance;
}
query(sql: string): void {
console.log(`[${this.connectionString}] Kör: ${sql}`);
}
}
// ── Klientkod ─────────────────────────────────────────────
const db1 = Database.getInstance('postgresql://localhost/bytebase');
const db2 = Database.getInstance('postgresql://localhost/bytebase');
console.log('Samma instans?', db1 === db2); // true
db1.query('SELECT * FROM patterns');
db2.query('INSERT INTO patterns VALUES (...)');
// Båda anropen går mot SAMMA anslutning
Output:
Databas initierad: postgresql://localhost/bytebase
Samma instans? true
[postgresql://localhost/bytebase] Kör: SELECT * FROM patterns
[postgresql://localhost/bytebase] Kör: INSERT INTO patterns VALUES (...)
Singleton i Node.js
I Node.js-moduler uppnår du ofta Singleton-beteende gratis via modulsystemet — en modul cachas efter första require/import:
// database.ts — exporteras som en singleton automatiskt av Node.js modul-cache
class Database {
private connectionString = 'postgresql://localhost/bytebase';
query(sql: string) { console.log(`Kör: ${sql}`); }
}
export const db = new Database(); // En instans, delad överallt
Fördelar
- Garanterar att en klass bara har en instans.
- Global åtkomstpunkt till instansen.
- Instansen initieras bara när den faktiskt behövs (lazy initialization).
Nackdelar
- Kan dölja dålig design — komponenter som vet för mycket om varandra.
- Svårt att enhetstest — Singletons bär tillstånd mellan tester.
- I TypeScript/JavaScript behöver du sällan mönstret explicit tack vare modulsystemet.
Av Victor Hernandez från Bytebase.se