Heim >Web-Frontend >js-Tutorial >Singleton-Entwurfsmuster: Globale Zustände in Ihren Anwendungen verwalten
Haben Sie jemals mit einem Objekt zu tun gehabt, das von mehreren Teilen Ihrer Anwendung gemeinsam genutzt werden muss – vielleicht einer Datenbankverbindung, einem WebSocket-Client oder einem Konfigurationsmanager?
Wie verwaltet man ein solches Objekt, damit es während des gesamten Anwendungs- oder Prozesslebenszyklus konsistent und zugänglich bleibt? Hier kommt das Singleton Design Pattern ins Spiel.
Singleton ist ein kreatives Designmuster, eine Kategorie von Designmustern, die sich mit den verschiedenen Problemen befasst, die mit der nativen Art der Objekterstellung mit dem Neuen einhergehen Schlüsselwort oder Operator.
Das Singleton Design Pattern konzentriert sich auf die Lösung von zwei Hauptproblemen:
Es kann die Art und Weise vereinfachen und standardisieren, wie wir eine bestimmte Art oder einen bestimmten Typ von globalen Zuständen verwalten, z. B. Datenbankverbindungen, WebSocket-Clients, Caching-Dienste oder alles, was wir während des gesamten Anwendungslebenszyklus im Speicher beibehalten und verändern müssen.
Das obige Schema wird in diese TypeScript-Klasse übersetzt:
TypeScript-Beispiel
class Singleton { private static instance: Singleton // other properties... public authorName: string private constructor({ authorName }: { authorName: string }) { this.authorName = authorName } public static getInstance(params) { if (!this.instance) { this.instance = new Singleton(params) } return this.instance } // other methods... }
Das Schlüsselwort static bedeutet, dass das Instanzobjekt nicht mit den Instanzen der Klasse, sondern mit der Klassendefinition selbst verknüpft ist.
const instance = Singleton.getInstance({ authorName: "Sidali Assoul" }) // let's imagine const instance1 = Singleton.getInstance({ authorName: "Sidali Assoul" }) // "Sidali Assoul" const instance2 = Singleton.getInstance({ authorName: "John Doe" }) // "Sidali Assoul"
Wir können die obige Klasse nutzen, indem wir die statische Methode getInstance aufrufen, die der Singleton-Klasse zugeordnet ist.
Die getInstance-Methode garantiert uns, dass wir immer dieselbe Instanz erhalten, auch wenn wir unsere Klasse mehrmals an verschiedenen Stellen unserer Codebasis instanziiert haben.
Also teilen sich beide Variablen (Instanz1 und Instanz2) dieselbe Singleton-Instanz.
Prisma ist ein bekanntes ORM im JavaScript-Ökosystem. Um Prisma in Ihrer Anwendung zu verwenden, müssen Sie einen PrismaClient importieren und dann ein Objekt daraus instanziieren.
class Singleton { private static instance: Singleton // other properties... public authorName: string private constructor({ authorName }: { authorName: string }) { this.authorName = authorName } public static getInstance(params) { if (!this.instance) { this.instance = new Singleton(params) } return this.instance } // other methods... }
Der Prisma-Client stellt eine verzögerte Verbindung zur Datenbank her, oder anders ausgedrückt, nur dann, wenn Sie zum ersten Mal versuchen, eine Entität abzufragen oder zu mutieren.
const instance = Singleton.getInstance({ authorName: "Sidali Assoul" }) // let's imagine const instance1 = Singleton.getInstance({ authorName: "Sidali Assoul" }) // "Sidali Assoul" const instance2 = Singleton.getInstance({ authorName: "John Doe" }) // "Sidali Assoul"
Jedes Mal, wenn der PrismaClient in eine Datei importiert wird, wird eine neue Instanz aus dem PrismaClient erstellt. Daher werden jedes Mal, wenn wir diese Instanzen verwenden, viele Datenbankverbindungen hergestellt.
import { PrismaClient } from "@prisma/client" export const prismaClient = new PrismaClient()
Viele offene Datenbankverbindungen beeinträchtigen die Leistung Ihrer Anwendung und können sogar zum Herunterfahren der Datenbank führen, da Datenbanken normalerweise nur eine begrenzte Anzahl von Verbindungen verarbeiten können.
Das Singleton-Entwurfsmuster kann uns dabei helfen, ein solches Problem zu verhindern, indem es mehr als eine Instanz der PrismaClient-Klasse vermeidet und einen einzigen Zugriffspunkt über die statische Methode PrismaClientSingleton.getInstance() bereitstellt.
import { prismaClient } from "@/db" const users = await prismaClient.user.findMany() // query on the users table
Ein weiteres praktisches Szenario, das wir durchgehen werden, ist ein In-Memory-Ratenbegrenzerdienst.
Benutzer oder Hacker können einen bestimmten Endpunkt spammen, indem sie eine Menge Anfragen an ihn stellen. Dies kann zu Schwachstellen, unerwarteten Kosten oder Serverausfällen führen.
Um dies zu verhindern, können wir einen grundlegenden In-Memory-Ratenbegrenzerdienst implementieren.
Der Dienst sollte die Anzahl der Anfragen pro IP-Adresse für ein bestimmtes Zeitfensterintervall (z. B. 60 Sekunden) begrenzen.
export const prismaClient = new PrismaClient() // a new instance is created every time it gets imported then used.
Die RateLimiterService-Klasse speichert eine Karte, die die Anzahl der Anfragen (requests[ip].count) verfolgt, die von einem bestimmten Benutzer gestellt werden, der durch eine IP-Adresse (den Kartenschlüssel) in einem bestimmten Zeitfenster identifiziert wird (requests[ip].lastRequestTime).
Unser RateLimiterService soll global verwendet werden, oder anders ausgedrückt: Wir möchten nicht jedes Mal, wenn der RateLimiterService importiert wird, die internen Statuswerte zurücksetzen, die aus den Anforderungskarten-, Limit- und Fenstervariablen bestehen.
Das Singleton Design Pattern ist ein leistungsstarkes Tool zur effektiven Verwaltung gemeinsam genutzter Ressourcen in unseren Anwendungen
Wichtige Erkenntnisse:
Wenn Sie Fragen haben oder etwas weiter besprechen möchten, können Sie mich gerne hier kontaktieren.
Viel Spaß beim Codieren!
Das obige ist der detaillierte Inhalt vonSingleton-Entwurfsmuster: Globale Zustände in Ihren Anwendungen verwalten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!