Zum Hauptinhalt springen

Singleton Pattern

Das Singleton-Muster stellt sicher, dass eine Klasse nur eine einzige Instanz hat und bietet globalen Zugriff darauf. Es wird oft verwendet, wenn nur eine Instanz einer Klasse benötigt wird, um eine zentrale Ressource zu verwalten oder um Kollisionen bei Ressourcenzugriffen zu vermeiden. Das Singleton-Muster stellt sicher, dass die Instanzierung der Klasse kontrolliert und die gleiche Instanz bei jedem Zugriff zurückgegeben wird.

UML

Beispiele

Beispiel eines threadsicheren Loggers

public class Logger
{
private static readonly object lockObject = new object();
private static Logger instance;

// Private Konstruktor, um die direkte Instanziierung zu verhindern
private Logger()
{
// Initialisierungslogik
}

// Statische Methode zum Abrufen der Singleton-Instanz
public static Logger GetInstance()
{
if (instance == null)
{
lock (lockObject)
{
if (instance == null)
{
instance = new Logger();
}
}
}
return instance;
}

// Log-Methode, um eine Nachricht zu protokollieren
public void Log(string message)
{
lock (lockObject)
{
// Protokollierungslogik hier
Console.WriteLine(message);
}
}
}

Dieser Logger ist thread-sicher, da er eine Sperre (lockObject) verwendet, um den Zugriff auf kritische Abschnitte des Codes zu synchronisieren. Dadurch wird sichergestellt, dass nur ein Thread gleichzeitig auf den Logger zugreifen und Nachrichten protokollieren kann. Das lock-Statement gewährleistet die Exklusivität des Zugriffs und verhindert Rennbedingungen.

Verwendung des Loggers

Logger logger = Logger.GetInstance();
logger.Log("Nachricht 1");
logger.Log("Nachricht 2");

Die Log-Methode protokolliert die übergebene Nachricht und stellt sicher, dass die Nachrichten synchronisiert und korrekt auf der Konsole ausgegeben werden, auch wenn mehrere Threads gleichzeitig darauf zugreifen.

Beispiel einer threadsicheren Datenbankverbindung

public class DatabaseConnection
{
private static readonly Lazy<DatabaseConnection> instance = new Lazy<DatabaseConnection>(() => new DatabaseConnection());

private SqlConnection connection;
private readonly object lockObject = new object();

private DatabaseConnection()
{
// Verbindung zur Datenbank initialisieren
connection = new SqlConnection("connectionString");
}

public static DatabaseConnection Instance => instance.Value;

public void OpenConnection()
{
lock (lockObject)
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
}
}

public void CloseConnection()
{
lock (lockObject)
{
if (connection.State != ConnectionState.Closed)
{
connection.Close();
}
}
}

public void ExecuteQuery(string query)
{
lock (lockObject)
{
// Code zum Ausführen der Datenbankabfrage
}
}
}

In diesem Beispiel wird die DatabaseConnection-Klasse als Singleton implementiert. Das Lazy<T>-Objekt sorgt dafür, dass die Singleton-Instanz nur einmal und erst dann erstellt wird, wenn sie benötigt wird.

Die connection-Variable ist privat und nur innerhalb der Klasse zugänglich. Die Methoden OpenConnection, CloseConnection und ExecuteQuery sind öffentlich und ermöglichen den Zugriff auf die Singleton-Instanz und die Ausführung von Datenbankoperationen.

Die Verwendung des lockObject-Objekts in den Methoden stellt sicher, dass die Datenbankverbindung threadsicher ist und nur von einem Thread gleichzeitig verwendet wird.

Um die Singleton-Datenbankverbindung zu nutzen, kannst du den folgenden Code verwenden:

DatabaseConnection connection = DatabaseConnection.Instance;
connection.OpenConnection();
connection.ExecuteQuery("SELECT * FROM TableName");
connection.CloseConnection();

Auf diese Weise erhältst du immer die gleiche Instanz der DatabaseConnection, und du kannst Datenbankoperationen sicher ausführen, unabhängig davon, wie viele Threads gleichzeitig darauf zugreifen.


Kommentare