Entwurfsmuster in C#: Vollständiger Leitfaden mit Beispielen
Entwurfsmuster (Design Patterns) sind bewährte Lösungen für typische Probleme, die bei der Softwareentwicklung auftreten. Im .NET- und C#-Ökosystem ist die Kenntnis von Mustern besonders wichtig, da viele von ihnen direkt in die Plattform integriert sind (z.B. IDisposable für das Dispose-Muster). In diesem Artikel werden wir die drei Hauptgruppen von Mustern nach der GoF-Klassifikation (Gang of Four) mit praktischen Beispielen in C# behandeln.
Erzeugungsmuster (Creational Patterns)
Erzeugungsmuster sind für die Objekterstellung verantwortlich und machen das System unabhängig von der Art und Weise ihrer Erstellung, Zusammensetzung und Darstellung.
Singleton (Einzelstück)
Stellt sicher, dass eine Klasse nur eine Instanz hat, und bietet einen globalen Zugriffspunkt darauf. In C# wird es häufig für die Arbeit mit Loggern, Caches oder Konfigurationen verwendet.
public sealed class Logger{ private static readonly Lazy<Logger> _instance = new Lazy<Logger>(() => new Logger());
public static Logger Instance => _instance.Value;
private Logger() { }
public void Log(string message) { Console.WriteLine($"[{DateTime.Now}] {message}"); }}
// VerwendungLogger.Instance.Log("Anwendung gestartet");Factory Method (Fabrikmethode)
Definiert eine Schnittstelle zur Erstellung eines Objekts, ermöglicht es Unterklassen jedoch, den Typ des erstellten Objekts zu ändern. Ideal für Logik, die erweiterbar sein soll.
public interface ITransport{ void Deliver();}
public class Truck : ITransport{ public void Deliver() => Console.WriteLine("Lieferung auf der Straße");}
public class Ship : ITransport{ public void Deliver() => Console.WriteLine("Lieferung auf dem Seeweg");}
public abstract class Logistics{ public abstract ITransport CreateTransport();
public void PlanDelivery() { var transport = CreateTransport(); transport.Deliver(); }}
public class RoadLogistics : Logistics{ public override ITransport CreateTransport() => new Truck();}
public class SeaLogistics : Logistics{ public override ITransport CreateTransport() => new Ship();}
// VerwendungLogistics logistics = new RoadLogistics();logistics.PlanDelivery(); // Lieferung auf der StraßeStrukturmuster (Structural Patterns)
Strukturmuster definieren Möglichkeiten zum Aufbau von Klassen und Objekten, um größere Strukturen zu bilden.
Adapter (Adapter)
Wandelt die Schnittstelle einer Klasse in eine andere Schnittstelle um, die der Client erwartet. Wird häufig für die Integration mit Drittanbieterbibliotheken oder Legacy-Code verwendet.
// Ziel-Schnittstelle (ITarget)public interface IXmlParser{ string ParseToXml(string data);}
// Anpassbare Klasse (Adaptee)public class JsonParser{ public string ParseToJson(string data) { return $"{{\\"data\\": \\"{data}\\"}}"; }}
// Adapterpublic class JsonToXmlAdapter : IXmlParser{ private readonly JsonParser _jsonParser;
public JsonToXmlAdapter(JsonParser jsonParser) { _jsonParser = jsonParser; }
public string ParseToXml(string data) { var json = _jsonParser.ParseToJson(data); // Einfachste Konvertierung von JSON in XML return $"<data>{data}</data>"; }}
// Verwendungvar adapter = new JsonToXmlAdapter(new JsonParser());string xml = adapter.ParseToXml("Hello");Console.WriteLine(xml); // <data>Hello</data>Decorator (Dekorierer)
Fügt einem Objekt dynamisch neue Aufgaben hinzu. In C# wird dieses Muster oft durch Vererbung oder Komposition implementiert.
public interface INotifier{ void Send(string message);}
public class E